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