1// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//    http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#ifndef _BASICTYPES_INCLUDED_
16#define _BASICTYPES_INCLUDED_
17
18#include "debug.h"
19
20//
21// Precision qualifiers
22//
23enum TPrecision : unsigned char
24{
25	// These need to be kept sorted
26	EbpUndefined,
27	EbpLow,
28	EbpMedium,
29	EbpHigh
30};
31
32inline const char *getPrecisionString(TPrecision precision)
33{
34	switch(precision)
35	{
36	case EbpHigh:		return "highp";		break;
37	case EbpMedium:		return "mediump";	break;
38	case EbpLow:		return "lowp";		break;
39	default:			return "mediump";   break;   // Safest fallback
40	}
41}
42
43//
44// Basic type.  Arrays, vectors, etc., are orthogonal to this.
45//
46enum TBasicType : unsigned char
47{
48	EbtVoid,
49	EbtFloat,
50	EbtInt,
51	EbtUInt,
52	EbtBool,
53	EbtGVec4,              // non type: represents vec4, ivec4, and uvec4
54	EbtGenType,            // non type: represents float, vec2, vec3, and vec4
55	EbtGenIType,           // non type: represents int, ivec2, ivec3, and ivec4
56	EbtGenUType,           // non type: represents uint, uvec2, uvec3, and uvec4
57	EbtGenBType,           // non type: represents bool, bvec2, bvec3, and bvec4
58	EbtVec,                // non type: represents vec2, vec3, and vec4
59	EbtIVec,               // non type: represents ivec2, ivec3, and ivec4
60	EbtUVec,               // non type: represents uvec2, uvec3, and uvec4
61	EbtBVec,               // non type: represents bvec2, bvec3, and bvec4
62	EbtGuardSamplerBegin,  // non type: see implementation of IsSampler()
63	EbtSampler2D,
64	EbtSampler3D,
65	EbtSamplerCube,
66	EbtSampler2DArray,
67	EbtSampler2DRect,       // Only valid if ARB_texture_rectangle exists.
68	EbtSamplerExternalOES,  // Only valid if OES_EGL_image_external exists.
69	EbtISampler2D,
70	EbtISampler3D,
71	EbtISamplerCube,
72	EbtISampler2DArray,
73	EbtUSampler2D,
74	EbtUSampler3D,
75	EbtUSamplerCube,
76	EbtUSampler2DArray,
77	EbtSampler2DShadow,
78	EbtSamplerCubeShadow,
79	EbtSampler2DArrayShadow,
80	EbtGuardSamplerEnd,    // non type: see implementation of IsSampler()
81	EbtGSampler2D,         // non type: represents sampler2D, isampler2D, and usampler2D
82	EbtGSampler3D,         // non type: represents sampler3D, isampler3D, and usampler3D
83	EbtGSamplerCube,       // non type: represents samplerCube, isamplerCube, and usamplerCube
84	EbtGSampler2DArray,    // non type: represents sampler2DArray, isampler2DArray, and usampler2DArray
85	EbtStruct,
86	EbtInterfaceBlock,
87	EbtAddress,            // should be deprecated??
88	EbtInvariant           // used as a type when qualifying a previously declared variable as being invariant
89};
90
91enum TLayoutMatrixPacking
92{
93	EmpUnspecified,
94	EmpRowMajor,
95	EmpColumnMajor
96};
97
98enum TLayoutBlockStorage
99{
100	EbsUnspecified,
101	EbsShared,
102	EbsPacked,
103	EbsStd140
104};
105
106inline const char *getBasicString(TBasicType type)
107{
108	switch(type)
109	{
110	case EbtVoid:               return "void";
111	case EbtFloat:              return "float";
112	case EbtInt:                return "int";
113	case EbtUInt:               return "uint";
114	case EbtBool:               return "bool";
115	case EbtSampler2D:          return "sampler2D";
116	case EbtSamplerCube:        return "samplerCube";
117	case EbtSampler2DRect:      return "sampler2DRect";
118	case EbtSamplerExternalOES: return "samplerExternalOES";
119	case EbtSampler3D:			return "sampler3D";
120	case EbtStruct:             return "structure";
121	default: UNREACHABLE(type); return "unknown type";
122	}
123}
124
125inline const char* getMatrixPackingString(TLayoutMatrixPacking mpq)
126{
127	switch(mpq)
128	{
129	case EmpUnspecified:    return "mp_unspecified";
130	case EmpRowMajor:       return "row_major";
131	case EmpColumnMajor:    return "column_major";
132	default: UNREACHABLE(mpq); return "unknown matrix packing";
133	}
134}
135
136inline const char* getBlockStorageString(TLayoutBlockStorage bsq)
137{
138	switch(bsq)
139	{
140	case EbsUnspecified:    return "bs_unspecified";
141	case EbsShared:         return "shared";
142	case EbsPacked:         return "packed";
143	case EbsStd140:         return "std140";
144	default: UNREACHABLE(bsq); return "unknown block storage";
145	}
146}
147
148inline bool IsSampler(TBasicType type)
149{
150	return type > EbtGuardSamplerBegin && type < EbtGuardSamplerEnd;
151}
152
153inline bool IsIntegerSampler(TBasicType type)
154{
155	switch(type)
156	{
157	case EbtISampler2D:
158	case EbtISampler3D:
159	case EbtISamplerCube:
160	case EbtISampler2DArray:
161	case EbtUSampler2D:
162	case EbtUSampler3D:
163	case EbtUSamplerCube:
164	case EbtUSampler2DArray:
165		return true;
166	case EbtSampler2D:
167	case EbtSampler3D:
168	case EbtSamplerCube:
169	case EbtSampler2DRect:
170	case EbtSamplerExternalOES:
171	case EbtSampler2DArray:
172	case EbtSampler2DShadow:
173	case EbtSamplerCubeShadow:
174	case EbtSampler2DArrayShadow:
175		return false;
176	default:
177		assert(!IsSampler(type));
178	}
179
180	return false;
181}
182
183inline bool IsSampler2D(TBasicType type)
184{
185	switch(type)
186	{
187	case EbtSampler2D:
188	case EbtISampler2D:
189	case EbtUSampler2D:
190	case EbtSampler2DArray:
191	case EbtISampler2DArray:
192	case EbtUSampler2DArray:
193	case EbtSampler2DRect:
194	case EbtSamplerExternalOES:
195	case EbtSampler2DShadow:
196	case EbtSampler2DArrayShadow:
197		return true;
198	case EbtSampler3D:
199	case EbtISampler3D:
200	case EbtUSampler3D:
201	case EbtISamplerCube:
202	case EbtUSamplerCube:
203	case EbtSamplerCube:
204	case EbtSamplerCubeShadow:
205		return false;
206	default:
207		assert(!IsSampler(type));
208	}
209
210	return false;
211}
212
213inline bool IsSamplerCube(TBasicType type)
214{
215	switch(type)
216	{
217	case EbtSamplerCube:
218	case EbtISamplerCube:
219	case EbtUSamplerCube:
220	case EbtSamplerCubeShadow:
221		return true;
222	case EbtSampler2D:
223	case EbtSampler3D:
224	case EbtSampler2DRect:
225	case EbtSamplerExternalOES:
226	case EbtSampler2DArray:
227	case EbtISampler2D:
228	case EbtISampler3D:
229	case EbtISampler2DArray:
230	case EbtUSampler2D:
231	case EbtUSampler3D:
232	case EbtUSampler2DArray:
233	case EbtSampler2DShadow:
234	case EbtSampler2DArrayShadow:
235		return false;
236	default:
237		assert(!IsSampler(type));
238	}
239
240	return false;
241}
242
243inline bool IsSampler3D(TBasicType type)
244{
245	switch(type)
246	{
247	case EbtSampler3D:
248	case EbtISampler3D:
249	case EbtUSampler3D:
250		return true;
251	case EbtSampler2D:
252	case EbtSamplerCube:
253	case EbtSampler2DRect:
254	case EbtSamplerExternalOES:
255	case EbtSampler2DArray:
256	case EbtISampler2D:
257	case EbtISamplerCube:
258	case EbtISampler2DArray:
259	case EbtUSampler2D:
260	case EbtUSamplerCube:
261	case EbtUSampler2DArray:
262	case EbtSampler2DShadow:
263	case EbtSamplerCubeShadow:
264	case EbtSampler2DArrayShadow:
265		return false;
266	default:
267		assert(!IsSampler(type));
268	}
269
270	return false;
271}
272
273inline bool IsSamplerArray(TBasicType type)
274{
275	switch(type)
276	{
277	case EbtSampler2DArray:
278	case EbtISampler2DArray:
279	case EbtUSampler2DArray:
280	case EbtSampler2DArrayShadow:
281		return true;
282	case EbtSampler2D:
283	case EbtISampler2D:
284	case EbtUSampler2D:
285	case EbtSampler2DRect:
286	case EbtSamplerExternalOES:
287	case EbtSampler3D:
288	case EbtISampler3D:
289	case EbtUSampler3D:
290	case EbtISamplerCube:
291	case EbtUSamplerCube:
292	case EbtSamplerCube:
293	case EbtSampler2DShadow:
294	case EbtSamplerCubeShadow:
295		return false;
296	default:
297		assert(!IsSampler(type));
298	}
299
300	return false;
301}
302
303inline bool IsShadowSampler(TBasicType type)
304{
305	switch(type)
306	{
307	case EbtSampler2DShadow:
308	case EbtSamplerCubeShadow:
309	case EbtSampler2DArrayShadow:
310		return true;
311	case EbtISampler2D:
312	case EbtISampler3D:
313	case EbtISamplerCube:
314	case EbtISampler2DArray:
315	case EbtUSampler2D:
316	case EbtUSampler3D:
317	case EbtUSamplerCube:
318	case EbtUSampler2DArray:
319	case EbtSampler2D:
320	case EbtSampler3D:
321	case EbtSamplerCube:
322	case EbtSampler2DRect:
323	case EbtSamplerExternalOES:
324	case EbtSampler2DArray:
325		return false;
326	default:
327		assert(!IsSampler(type));
328	}
329
330	return false;
331}
332
333inline bool IsInteger(TBasicType type)
334{
335	return type == EbtInt || type == EbtUInt;
336}
337
338inline bool SupportsPrecision(TBasicType type)
339{
340	return type == EbtFloat || type == EbtInt || type == EbtUInt || IsSampler(type);
341}
342
343//
344// Qualifiers and built-ins.  These are mainly used to see what can be read
345// or written, and by the machine dependent translator to know which registers
346// to allocate variables in.  Since built-ins tend to go to different registers
347// than varying or uniform, it makes sense they are peers, not sub-classes.
348//
349enum TQualifier : unsigned char
350{
351	EvqTemporary,     // For temporaries (within a function), read/write
352	EvqGlobal,        // For globals read/write
353	EvqConstExpr,     // User defined constants
354	EvqAttribute,     // Readonly
355	EvqVaryingIn,     // readonly, fragment shaders only
356	EvqVaryingOut,    // vertex shaders only  read/write
357	EvqInvariantVaryingIn,     // readonly, fragment shaders only
358	EvqInvariantVaryingOut,    // vertex shaders only  read/write
359	EvqUniform,       // Readonly, vertex and fragment
360
361	EvqVertexIn,      // Vertex shader input
362	EvqFragmentOut,   // Fragment shader output
363	EvqVertexOut,     // Vertex shader output
364	EvqFragmentIn,    // Fragment shader input
365
366	// pack/unpack input and output
367	EvqInput,
368	EvqOutput,
369
370	// parameters
371	EvqIn,
372	EvqOut,
373	EvqInOut,
374	EvqConstReadOnly,
375
376	// built-ins written by vertex shader
377	EvqPosition,
378	EvqPointSize,
379	EvqInstanceID,
380	EvqVertexID,
381
382	// built-ins read by fragment shader
383	EvqFragCoord,
384	EvqFrontFacing,
385	EvqPointCoord,
386
387	// built-ins written by fragment shader
388	EvqFragColor,
389	EvqFragData,
390	EvqFragDepth,
391
392	// GLSL ES 3.0 vertex output and fragment input
393	EvqSmooth,        // Incomplete qualifier, smooth is the default
394	EvqFlat,          // Incomplete qualifier
395	EvqSmoothOut = EvqSmooth,
396	EvqFlatOut = EvqFlat,
397	EvqCentroidOut,   // Implies smooth
398	EvqSmoothIn,
399	EvqFlatIn,
400	EvqCentroidIn,    // Implies smooth
401
402	// end of list
403	EvqLast
404};
405
406struct TLayoutQualifier
407{
408	static TLayoutQualifier create()
409	{
410		TLayoutQualifier layoutQualifier;
411
412		layoutQualifier.location = -1;
413		layoutQualifier.matrixPacking = EmpUnspecified;
414		layoutQualifier.blockStorage = EbsUnspecified;
415
416		return layoutQualifier;
417	}
418
419	bool isEmpty() const
420	{
421		return location == -1 && matrixPacking == EmpUnspecified && blockStorage == EbsUnspecified;
422	}
423
424	int location;
425	TLayoutMatrixPacking matrixPacking;
426	TLayoutBlockStorage blockStorage;
427};
428
429//
430// This is just for debug print out, carried along with the definitions above.
431//
432inline const char *getQualifierString(TQualifier qualifier)
433{
434	switch(qualifier)
435	{
436	case EvqTemporary:      return "Temporary";      break;
437	case EvqGlobal:         return "Global";         break;
438	case EvqConstExpr:      return "const";          break;
439	case EvqConstReadOnly:  return "const";          break;
440	case EvqAttribute:      return "attribute";      break;
441	case EvqVaryingIn:      return "varying";        break;
442	case EvqVaryingOut:     return "varying";        break;
443	case EvqInvariantVaryingIn: return "invariant varying";	break;
444	case EvqInvariantVaryingOut:return "invariant varying";	break;
445	case EvqUniform:        return "uniform";        break;
446	case EvqVertexIn:       return "in";             break;
447	case EvqFragmentOut:    return "out";            break;
448	case EvqVertexOut:      return "out";            break;
449	case EvqFragmentIn:     return "in";             break;
450	case EvqIn:             return "in";             break;
451	case EvqOut:            return "out";            break;
452	case EvqInOut:          return "inout";          break;
453	case EvqInput:          return "input";          break;
454	case EvqOutput:         return "output";         break;
455	case EvqPosition:       return "Position";       break;
456	case EvqPointSize:      return "PointSize";      break;
457	case EvqInstanceID:     return "InstanceID";     break;
458	case EvqVertexID:       return "VertexID";       break;
459	case EvqFragCoord:      return "FragCoord";      break;
460	case EvqFrontFacing:    return "FrontFacing";    break;
461	case EvqFragColor:      return "FragColor";      break;
462	case EvqFragData:       return "FragData";       break;
463	case EvqFragDepth:      return "FragDepth";      break;
464	case EvqSmooth:         return "Smooth";         break;
465	case EvqFlat:           return "Flat";           break;
466	case EvqCentroidOut:    return "CentroidOut";    break;
467	case EvqSmoothIn:       return "SmoothIn";       break;
468	case EvqFlatIn:         return "FlatIn";         break;
469	case EvqCentroidIn:     return "CentroidIn";     break;
470	default: UNREACHABLE(qualifier); return "unknown qualifier";
471	}
472}
473
474#endif // _BASICTYPES_INCLUDED_
475