• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 //
8 // Implement the top-level of interface to the compiler,
9 // as defined in ShaderLang.h
10 //
11 
12 #include "GLSLANG/ShaderLang.h"
13 
14 #include "compiler/InitializeDll.h"
15 #include "compiler/preprocessor/length_limits.h"
16 #include "compiler/ShHandle.h"
17 #include "compiler/TranslatorHLSL.h"
18 #include "compiler/VariablePacker.h"
19 
20 //
21 // This is the platform independent interface between an OGL driver
22 // and the shading language compiler.
23 //
24 
checkVariableMaxLengths(const ShHandle handle,size_t expectedValue)25 static bool checkVariableMaxLengths(const ShHandle handle,
26                                     size_t expectedValue)
27 {
28     size_t activeUniformLimit = 0;
29     ShGetInfo(handle, SH_ACTIVE_UNIFORM_MAX_LENGTH, &activeUniformLimit);
30     size_t activeAttribLimit = 0;
31     ShGetInfo(handle, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, &activeAttribLimit);
32     size_t varyingLimit = 0;
33     ShGetInfo(handle, SH_VARYING_MAX_LENGTH, &varyingLimit);
34     return (expectedValue == activeUniformLimit &&
35             expectedValue == activeAttribLimit &&
36             expectedValue == varyingLimit);
37 }
38 
checkMappedNameMaxLength(const ShHandle handle,size_t expectedValue)39 static bool checkMappedNameMaxLength(const ShHandle handle, size_t expectedValue)
40 {
41     size_t mappedNameMaxLength = 0;
42     ShGetInfo(handle, SH_MAPPED_NAME_MAX_LENGTH, &mappedNameMaxLength);
43     return (expectedValue == mappedNameMaxLength);
44 }
45 
46 //
47 // Driver must call this first, once, before doing any other compiler operations.
48 // Subsequent calls to this function are no-op.
49 //
ShInitialize()50 int ShInitialize()
51 {
52     static const bool kInitialized = InitProcess();
53     return kInitialized ? 1 : 0;
54 }
55 
56 //
57 // Cleanup symbol tables
58 //
ShFinalize()59 int ShFinalize()
60 {
61     DetachProcess();
62     return 1;
63 }
64 
65 //
66 // Initialize built-in resources with minimum expected values.
67 //
ShInitBuiltInResources(ShBuiltInResources * resources)68 void ShInitBuiltInResources(ShBuiltInResources* resources)
69 {
70     // Constants.
71     resources->MaxVertexAttribs = 8;
72     resources->MaxVertexUniformVectors = 128;
73     resources->MaxVaryingVectors = 8;
74     resources->MaxVertexTextureImageUnits = 0;
75     resources->MaxCombinedTextureImageUnits = 8;
76     resources->MaxTextureImageUnits = 8;
77     resources->MaxFragmentUniformVectors = 16;
78     resources->MaxDrawBuffers = 1;
79 
80     // Extensions.
81     resources->OES_standard_derivatives = 0;
82     resources->OES_EGL_image_external = 0;
83     resources->ARB_texture_rectangle = 0;
84     resources->EXT_draw_buffers = 0;
85     resources->EXT_frag_depth = 0;
86 
87     // Disable highp precision in fragment shader by default.
88     resources->FragmentPrecisionHigh = 0;
89 
90     // Disable name hashing by default.
91     resources->HashFunction = NULL;
92 
93     resources->ArrayIndexClampingStrategy = SH_CLAMP_WITH_CLAMP_INTRINSIC;
94 }
95 
96 //
97 // Driver calls these to create and destroy compiler objects.
98 //
ShConstructCompiler(ShShaderType type,ShShaderSpec spec,ShShaderOutput output,const ShBuiltInResources * resources)99 ShHandle ShConstructCompiler(ShShaderType type, ShShaderSpec spec,
100                              ShShaderOutput output,
101                              const ShBuiltInResources* resources)
102 {
103     TShHandleBase* base = static_cast<TShHandleBase*>(ConstructCompiler(type, spec, output));
104     TCompiler* compiler = base->getAsCompiler();
105     if (compiler == 0)
106         return 0;
107 
108     // Generate built-in symbol table.
109     if (!compiler->Init(*resources)) {
110         ShDestruct(base);
111         return 0;
112     }
113 
114     return reinterpret_cast<void*>(base);
115 }
116 
ShDestruct(ShHandle handle)117 void ShDestruct(ShHandle handle)
118 {
119     if (handle == 0)
120         return;
121 
122     TShHandleBase* base = static_cast<TShHandleBase*>(handle);
123 
124     if (base->getAsCompiler())
125         DeleteCompiler(base->getAsCompiler());
126 }
127 
128 //
129 // Do an actual compile on the given strings.  The result is left
130 // in the given compile object.
131 //
132 // Return:  The return value of ShCompile is really boolean, indicating
133 // success or failure.
134 //
ShCompile(const ShHandle handle,const char * const shaderStrings[],size_t numStrings,int compileOptions)135 int ShCompile(
136     const ShHandle handle,
137     const char* const shaderStrings[],
138     size_t numStrings,
139     int compileOptions)
140 {
141     if (handle == 0)
142         return 0;
143 
144     TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
145     TCompiler* compiler = base->getAsCompiler();
146     if (compiler == 0)
147         return 0;
148 
149     bool success = compiler->compile(shaderStrings, numStrings, compileOptions);
150     return success ? 1 : 0;
151 }
152 
ShGetInfo(const ShHandle handle,ShShaderInfo pname,size_t * params)153 void ShGetInfo(const ShHandle handle, ShShaderInfo pname, size_t* params)
154 {
155     if (!handle || !params)
156         return;
157 
158     TShHandleBase* base = static_cast<TShHandleBase*>(handle);
159     TCompiler* compiler = base->getAsCompiler();
160     if (!compiler) return;
161 
162     switch(pname)
163     {
164     case SH_INFO_LOG_LENGTH:
165         *params = compiler->getInfoSink().info.size() + 1;
166         break;
167     case SH_OBJECT_CODE_LENGTH:
168         *params = compiler->getInfoSink().obj.size() + 1;
169         break;
170     case SH_ACTIVE_UNIFORMS:
171         *params = compiler->getUniforms().size();
172         break;
173     case SH_ACTIVE_UNIFORM_MAX_LENGTH:
174         *params = 1 +  MAX_SYMBOL_NAME_LEN;
175         break;
176     case SH_ACTIVE_ATTRIBUTES:
177         *params = compiler->getAttribs().size();
178         break;
179     case SH_ACTIVE_ATTRIBUTE_MAX_LENGTH:
180         *params = 1 + MAX_SYMBOL_NAME_LEN;
181         break;
182     case SH_VARYINGS:
183         *params = compiler->getVaryings().size();
184         break;
185     case SH_VARYING_MAX_LENGTH:
186         *params = 1 + MAX_SYMBOL_NAME_LEN;
187         break;
188     case SH_MAPPED_NAME_MAX_LENGTH:
189         // Use longer length than MAX_SHORTENED_IDENTIFIER_SIZE to
190         // handle array and struct dereferences.
191         *params = 1 + MAX_SYMBOL_NAME_LEN;
192         break;
193     case SH_NAME_MAX_LENGTH:
194         *params = 1 + MAX_SYMBOL_NAME_LEN;
195         break;
196     case SH_HASHED_NAME_MAX_LENGTH:
197         if (compiler->getHashFunction() == NULL) {
198             *params = 0;
199         } else {
200             // 64 bits hashing output requires 16 bytes for hex
201             // representation.
202             const char HashedNamePrefix[] = HASHED_NAME_PREFIX;
203             *params = 16 + sizeof(HashedNamePrefix);
204         }
205         break;
206     case SH_HASHED_NAMES_COUNT:
207         *params = compiler->getNameMap().size();
208         break;
209     default: UNREACHABLE();
210     }
211 }
212 
213 //
214 // Return any compiler log of messages for the application.
215 //
ShGetInfoLog(const ShHandle handle,char * infoLog)216 void ShGetInfoLog(const ShHandle handle, char* infoLog)
217 {
218     if (!handle || !infoLog)
219         return;
220 
221     TShHandleBase* base = static_cast<TShHandleBase*>(handle);
222     TCompiler* compiler = base->getAsCompiler();
223     if (!compiler) return;
224 
225     TInfoSink& infoSink = compiler->getInfoSink();
226     strcpy(infoLog, infoSink.info.c_str());
227 }
228 
229 //
230 // Return any object code.
231 //
ShGetObjectCode(const ShHandle handle,char * objCode)232 void ShGetObjectCode(const ShHandle handle, char* objCode)
233 {
234     if (!handle || !objCode)
235         return;
236 
237     TShHandleBase* base = static_cast<TShHandleBase*>(handle);
238     TCompiler* compiler = base->getAsCompiler();
239     if (!compiler) return;
240 
241     TInfoSink& infoSink = compiler->getInfoSink();
242     strcpy(objCode, infoSink.obj.c_str());
243 }
244 
ShGetVariableInfo(const ShHandle handle,ShShaderInfo varType,int index,size_t * length,int * size,ShDataType * type,ShPrecisionType * precision,int * staticUse,char * name,char * mappedName)245 void ShGetVariableInfo(const ShHandle handle,
246                        ShShaderInfo varType,
247                        int index,
248                        size_t* length,
249                        int* size,
250                        ShDataType* type,
251                        ShPrecisionType* precision,
252                        int* staticUse,
253                        char* name,
254                        char* mappedName)
255 {
256     if (!handle || !size || !type || !precision || !staticUse || !name)
257         return;
258     ASSERT((varType == SH_ACTIVE_ATTRIBUTES) ||
259            (varType == SH_ACTIVE_UNIFORMS) ||
260            (varType == SH_VARYINGS));
261 
262     TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
263     TCompiler* compiler = base->getAsCompiler();
264     if (compiler == 0)
265         return;
266 
267     const TVariableInfoList& varList =
268         varType == SH_ACTIVE_ATTRIBUTES ? compiler->getAttribs() :
269             (varType == SH_ACTIVE_UNIFORMS ? compiler->getUniforms() :
270                 compiler->getVaryings());
271     if (index < 0 || index >= static_cast<int>(varList.size()))
272         return;
273 
274     const TVariableInfo& varInfo = varList[index];
275     if (length) *length = varInfo.name.size();
276     *size = varInfo.size;
277     *type = varInfo.type;
278     switch (varInfo.precision) {
279     case EbpLow:
280         *precision = SH_PRECISION_LOWP;
281         break;
282     case EbpMedium:
283         *precision = SH_PRECISION_MEDIUMP;
284         break;
285     case EbpHigh:
286         *precision = SH_PRECISION_HIGHP;
287         break;
288     default:
289         // Some types does not support precision, for example, boolean.
290         *precision = SH_PRECISION_UNDEFINED;
291         break;
292     }
293     *staticUse = varInfo.staticUse ? 1 : 0;
294 
295     // This size must match that queried by
296     // SH_ACTIVE_UNIFORM_MAX_LENGTH, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, SH_VARYING_MAX_LENGTH
297     // in ShGetInfo, below.
298     size_t variableLength = 1 + MAX_SYMBOL_NAME_LEN;
299     ASSERT(checkVariableMaxLengths(handle, variableLength));
300     strncpy(name, varInfo.name.c_str(), variableLength);
301     name[variableLength - 1] = 0;
302     if (mappedName) {
303         // This size must match that queried by
304         // SH_MAPPED_NAME_MAX_LENGTH in ShGetInfo, below.
305         size_t maxMappedNameLength = 1 + MAX_SYMBOL_NAME_LEN;
306         ASSERT(checkMappedNameMaxLength(handle, maxMappedNameLength));
307         strncpy(mappedName, varInfo.mappedName.c_str(), maxMappedNameLength);
308         mappedName[maxMappedNameLength - 1] = 0;
309     }
310 }
311 
ShGetNameHashingEntry(const ShHandle handle,int index,char * name,char * hashedName)312 void ShGetNameHashingEntry(const ShHandle handle,
313                            int index,
314                            char* name,
315                            char* hashedName)
316 {
317     if (!handle || !name || !hashedName || index < 0)
318         return;
319 
320     TShHandleBase* base = static_cast<TShHandleBase*>(handle);
321     TCompiler* compiler = base->getAsCompiler();
322     if (!compiler) return;
323 
324     const NameMap& nameMap = compiler->getNameMap();
325     if (index >= static_cast<int>(nameMap.size()))
326         return;
327 
328     NameMap::const_iterator it = nameMap.begin();
329     for (int i = 0; i < index; ++i)
330         ++it;
331 
332     size_t len = it->first.length() + 1;
333     size_t max_len = 0;
334     ShGetInfo(handle, SH_NAME_MAX_LENGTH, &max_len);
335     if (len > max_len) {
336         ASSERT(false);
337         len = max_len;
338     }
339     strncpy(name, it->first.c_str(), len);
340     // To be on the safe side in case the source is longer than expected.
341     name[len - 1] = '\0';
342 
343     len = it->second.length() + 1;
344     max_len = 0;
345     ShGetInfo(handle, SH_HASHED_NAME_MAX_LENGTH, &max_len);
346     if (len > max_len) {
347         ASSERT(false);
348         len = max_len;
349     }
350     strncpy(hashedName, it->second.c_str(), len);
351     // To be on the safe side in case the source is longer than expected.
352     hashedName[len - 1] = '\0';
353 }
354 
ShGetInfoPointer(const ShHandle handle,ShShaderInfo pname,void ** params)355 void ShGetInfoPointer(const ShHandle handle, ShShaderInfo pname, void** params)
356 {
357     if (!handle || !params)
358         return;
359 
360     TShHandleBase* base = static_cast<TShHandleBase*>(handle);
361     TranslatorHLSL* translator = base->getAsTranslatorHLSL();
362     if (!translator) return;
363 
364     switch(pname)
365     {
366     case SH_ACTIVE_UNIFORMS_ARRAY:
367         *params = (void*)&translator->getUniforms();
368         break;
369     default: UNREACHABLE();
370     }
371 }
372 
ShCheckVariablesWithinPackingLimits(int maxVectors,ShVariableInfo * varInfoArray,size_t varInfoArraySize)373 int ShCheckVariablesWithinPackingLimits(
374     int maxVectors, ShVariableInfo* varInfoArray, size_t varInfoArraySize)
375 {
376     if (varInfoArraySize == 0)
377         return 1;
378     ASSERT(varInfoArray);
379     TVariableInfoList variables;
380     for (size_t ii = 0; ii < varInfoArraySize; ++ii)
381     {
382         TVariableInfo var(varInfoArray[ii].type, varInfoArray[ii].size);
383         variables.push_back(var);
384     }
385     VariablePacker packer;
386     return packer.CheckVariablesWithinPackingLimits(maxVectors, variables) ? 1 : 0;
387 }
388