• 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/Compiler.h"
15 #include "compiler/translator/InitializeDll.h"
16 #include "compiler/translator/length_limits.h"
17 #include "compiler/translator/TranslatorHLSL.h"
18 #include "compiler/translator/VariablePacker.h"
19 #include "angle_gl.h"
20 
21 namespace
22 {
23 
24 enum ShaderVariableType
25 {
26     SHADERVAR_UNIFORM,
27     SHADERVAR_VARYING,
28     SHADERVAR_ATTRIBUTE,
29     SHADERVAR_OUTPUTVARIABLE,
30     SHADERVAR_INTERFACEBLOCK
31 };
32 
33 bool isInitialized = false;
34 
35 //
36 // This is the platform independent interface between an OGL driver
37 // and the shading language compiler.
38 //
39 
CheckVariableMaxLengths(const ShHandle handle,size_t expectedValue)40 static bool CheckVariableMaxLengths(const ShHandle handle,
41                                     size_t expectedValue)
42 {
43     size_t activeUniformLimit = 0;
44     ShGetInfo(handle, SH_ACTIVE_UNIFORM_MAX_LENGTH, &activeUniformLimit);
45     size_t activeAttribLimit = 0;
46     ShGetInfo(handle, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, &activeAttribLimit);
47     size_t varyingLimit = 0;
48     ShGetInfo(handle, SH_VARYING_MAX_LENGTH, &varyingLimit);
49     return (expectedValue == activeUniformLimit &&
50             expectedValue == activeAttribLimit &&
51             expectedValue == varyingLimit);
52 }
53 
CheckMappedNameMaxLength(const ShHandle handle,size_t expectedValue)54 bool CheckMappedNameMaxLength(const ShHandle handle, size_t expectedValue)
55 {
56     size_t mappedNameMaxLength = 0;
57     ShGetInfo(handle, SH_MAPPED_NAME_MAX_LENGTH, &mappedNameMaxLength);
58     return (expectedValue == mappedNameMaxLength);
59 }
60 
61 template <typename VarT>
ReturnVariable(const std::vector<VarT> & infoList,int index)62 const sh::ShaderVariable *ReturnVariable(const std::vector<VarT> &infoList, int index)
63 {
64     if (index < 0 || static_cast<size_t>(index) >= infoList.size())
65     {
66         return NULL;
67     }
68 
69     return &infoList[index];
70 }
71 
GetVariable(const TCompiler * compiler,ShShaderInfo varType,int index)72 const sh::ShaderVariable *GetVariable(const TCompiler *compiler, ShShaderInfo varType, int index)
73 {
74     switch (varType)
75     {
76       case SH_ACTIVE_ATTRIBUTES:
77         return ReturnVariable(compiler->getAttributes(), index);
78       case SH_ACTIVE_UNIFORMS:
79         return ReturnVariable(compiler->getExpandedUniforms(), index);
80       case SH_VARYINGS:
81         return ReturnVariable(compiler->getExpandedVaryings(), index);
82       default:
83         UNREACHABLE();
84         return NULL;
85     }
86 }
87 
ConvertPrecision(sh::GLenum precision)88 ShPrecisionType ConvertPrecision(sh::GLenum precision)
89 {
90     switch (precision)
91     {
92       case GL_HIGH_FLOAT:
93       case GL_HIGH_INT:
94         return SH_PRECISION_HIGHP;
95       case GL_MEDIUM_FLOAT:
96       case GL_MEDIUM_INT:
97         return SH_PRECISION_MEDIUMP;
98       case GL_LOW_FLOAT:
99       case GL_LOW_INT:
100         return SH_PRECISION_LOWP;
101       default:
102         return SH_PRECISION_UNDEFINED;
103     }
104 }
105 
106 template <typename VarT>
107 const std::vector<VarT> *GetVariableList(const TCompiler *compiler, ShaderVariableType variableType);
108 
109 template <>
GetVariableList(const TCompiler * compiler,ShaderVariableType)110 const std::vector<sh::Uniform> *GetVariableList(const TCompiler *compiler, ShaderVariableType)
111 {
112     return &compiler->getUniforms();
113 }
114 
115 template <>
GetVariableList(const TCompiler * compiler,ShaderVariableType)116 const std::vector<sh::Varying> *GetVariableList(const TCompiler *compiler, ShaderVariableType)
117 {
118     return &compiler->getVaryings();
119 }
120 
121 template <>
GetVariableList(const TCompiler * compiler,ShaderVariableType variableType)122 const std::vector<sh::Attribute> *GetVariableList(const TCompiler *compiler, ShaderVariableType variableType)
123 {
124     return (variableType == SHADERVAR_ATTRIBUTE ?
125         &compiler->getAttributes() :
126         &compiler->getOutputVariables());
127 }
128 
129 template <>
GetVariableList(const TCompiler * compiler,ShaderVariableType)130 const std::vector<sh::InterfaceBlock> *GetVariableList(const TCompiler *compiler, ShaderVariableType)
131 {
132     return &compiler->getInterfaceBlocks();
133 }
134 
135 template <typename VarT>
GetShaderVariables(const ShHandle handle,ShaderVariableType variableType)136 const std::vector<VarT> *GetShaderVariables(const ShHandle handle, ShaderVariableType variableType)
137 {
138     if (!handle)
139     {
140         return NULL;
141     }
142 
143     TShHandleBase* base = static_cast<TShHandleBase*>(handle);
144     TCompiler* compiler = base->getAsCompiler();
145     if (!compiler)
146     {
147         return NULL;
148     }
149 
150     return GetVariableList<VarT>(compiler, variableType);
151 }
152 
153 }
154 
155 //
156 // Driver must call this first, once, before doing any other compiler operations.
157 // Subsequent calls to this function are no-op.
158 //
ShInitialize()159 int ShInitialize()
160 {
161     if (!isInitialized)
162     {
163         isInitialized = InitProcess();
164     }
165     return isInitialized ? 1 : 0;
166 }
167 
168 //
169 // Cleanup symbol tables
170 //
ShFinalize()171 int ShFinalize()
172 {
173     if (isInitialized)
174     {
175         DetachProcess();
176         isInitialized = false;
177     }
178     return 1;
179 }
180 
181 //
182 // Initialize built-in resources with minimum expected values.
183 //
ShInitBuiltInResources(ShBuiltInResources * resources)184 void ShInitBuiltInResources(ShBuiltInResources* resources)
185 {
186     // Constants.
187     resources->MaxVertexAttribs = 8;
188     resources->MaxVertexUniformVectors = 128;
189     resources->MaxVaryingVectors = 8;
190     resources->MaxVertexTextureImageUnits = 0;
191     resources->MaxCombinedTextureImageUnits = 8;
192     resources->MaxTextureImageUnits = 8;
193     resources->MaxFragmentUniformVectors = 16;
194     resources->MaxDrawBuffers = 1;
195 
196     // Extensions.
197     resources->OES_standard_derivatives = 0;
198     resources->OES_EGL_image_external = 0;
199     resources->ARB_texture_rectangle = 0;
200     resources->EXT_draw_buffers = 0;
201     resources->EXT_frag_depth = 0;
202     resources->EXT_shader_texture_lod = 0;
203 
204     // Disable highp precision in fragment shader by default.
205     resources->FragmentPrecisionHigh = 0;
206 
207     // GLSL ES 3.0 constants.
208     resources->MaxVertexOutputVectors = 16;
209     resources->MaxFragmentInputVectors = 15;
210     resources->MinProgramTexelOffset = -8;
211     resources->MaxProgramTexelOffset = 7;
212 
213     // Disable name hashing by default.
214     resources->HashFunction = NULL;
215 
216     resources->ArrayIndexClampingStrategy = SH_CLAMP_WITH_CLAMP_INTRINSIC;
217 
218     resources->MaxExpressionComplexity = 256;
219     resources->MaxCallStackDepth = 256;
220 }
221 
222 //
223 // Driver calls these to create and destroy compiler objects.
224 //
ShConstructCompiler(sh::GLenum type,ShShaderSpec spec,ShShaderOutput output,const ShBuiltInResources * resources)225 ShHandle ShConstructCompiler(sh::GLenum type, ShShaderSpec spec,
226                              ShShaderOutput output,
227                              const ShBuiltInResources* resources)
228 {
229     TShHandleBase* base = static_cast<TShHandleBase*>(ConstructCompiler(type, spec, output));
230     TCompiler* compiler = base->getAsCompiler();
231     if (compiler == 0)
232         return 0;
233 
234     // Generate built-in symbol table.
235     if (!compiler->Init(*resources)) {
236         ShDestruct(base);
237         return 0;
238     }
239 
240     return reinterpret_cast<void*>(base);
241 }
242 
ShDestruct(ShHandle handle)243 void ShDestruct(ShHandle handle)
244 {
245     if (handle == 0)
246         return;
247 
248     TShHandleBase* base = static_cast<TShHandleBase*>(handle);
249 
250     if (base->getAsCompiler())
251         DeleteCompiler(base->getAsCompiler());
252 }
253 
ShGetBuiltInResourcesString(const ShHandle handle,size_t outStringLen,char * outString)254 void ShGetBuiltInResourcesString(const ShHandle handle, size_t outStringLen, char *outString)
255 {
256     if (!handle || !outString)
257     {
258         return;
259     }
260 
261     TShHandleBase *base = static_cast<TShHandleBase*>(handle);
262     TCompiler *compiler = base->getAsCompiler();
263     if (!compiler)
264     {
265         return;
266     }
267 
268     strncpy(outString, compiler->getBuiltInResourcesString().c_str(), outStringLen);
269     outString[outStringLen - 1] = '\0';
270 }
271 //
272 // Do an actual compile on the given strings.  The result is left
273 // in the given compile object.
274 //
275 // Return:  The return value of ShCompile is really boolean, indicating
276 // success or failure.
277 //
ShCompile(const ShHandle handle,const char * const shaderStrings[],size_t numStrings,int compileOptions)278 int ShCompile(
279     const ShHandle handle,
280     const char* const shaderStrings[],
281     size_t numStrings,
282     int compileOptions)
283 {
284     if (handle == 0)
285         return 0;
286 
287     TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
288     TCompiler* compiler = base->getAsCompiler();
289     if (compiler == 0)
290         return 0;
291 
292     bool success = compiler->compile(shaderStrings, numStrings, compileOptions);
293     return success ? 1 : 0;
294 }
295 
ShGetInfo(const ShHandle handle,ShShaderInfo pname,size_t * params)296 void ShGetInfo(const ShHandle handle, ShShaderInfo pname, size_t* params)
297 {
298     if (!handle || !params)
299         return;
300 
301     TShHandleBase* base = static_cast<TShHandleBase*>(handle);
302     TCompiler* compiler = base->getAsCompiler();
303     if (!compiler) return;
304 
305     switch(pname)
306     {
307     case SH_INFO_LOG_LENGTH:
308         *params = compiler->getInfoSink().info.size() + 1;
309         break;
310     case SH_OBJECT_CODE_LENGTH:
311         *params = compiler->getInfoSink().obj.size() + 1;
312         break;
313     case SH_ACTIVE_UNIFORMS:
314         *params = compiler->getExpandedUniforms().size();
315         break;
316     case SH_ACTIVE_UNIFORM_MAX_LENGTH:
317         *params = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec());
318         break;
319     case SH_ACTIVE_ATTRIBUTES:
320         *params = compiler->getAttributes().size();
321         break;
322     case SH_ACTIVE_ATTRIBUTE_MAX_LENGTH:
323         *params = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec());
324         break;
325     case SH_VARYINGS:
326         *params = compiler->getExpandedVaryings().size();
327         break;
328     case SH_VARYING_MAX_LENGTH:
329         *params = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec());
330         break;
331     case SH_MAPPED_NAME_MAX_LENGTH:
332         // Use longer length than MAX_SHORTENED_IDENTIFIER_SIZE to
333         // handle array and struct dereferences.
334         *params = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec());
335         break;
336     case SH_NAME_MAX_LENGTH:
337         *params = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec());
338         break;
339     case SH_HASHED_NAME_MAX_LENGTH:
340         if (compiler->getHashFunction() == NULL) {
341             *params = 0;
342         } else {
343             // 64 bits hashing output requires 16 bytes for hex
344             // representation.
345             const char HashedNamePrefix[] = HASHED_NAME_PREFIX;
346             (void)HashedNamePrefix;
347             *params = 16 + sizeof(HashedNamePrefix);
348         }
349         break;
350     case SH_HASHED_NAMES_COUNT:
351         *params = compiler->getNameMap().size();
352         break;
353     case SH_SHADER_VERSION:
354         *params = compiler->getShaderVersion();
355         break;
356     case SH_RESOURCES_STRING_LENGTH:
357         *params = compiler->getBuiltInResourcesString().length() + 1;
358         break;
359     case SH_OUTPUT_TYPE:
360         *params = compiler->getOutputType();
361         break;
362     default: UNREACHABLE();
363     }
364 }
365 
366 //
367 // Return any compiler log of messages for the application.
368 //
ShGetInfoLog(const ShHandle handle,char * infoLog)369 void ShGetInfoLog(const ShHandle handle, char* infoLog)
370 {
371     if (!handle || !infoLog)
372         return;
373 
374     TShHandleBase* base = static_cast<TShHandleBase*>(handle);
375     TCompiler* compiler = base->getAsCompiler();
376     if (!compiler) return;
377 
378     TInfoSink& infoSink = compiler->getInfoSink();
379     strcpy(infoLog, infoSink.info.c_str());
380 }
381 
382 //
383 // Return any object code.
384 //
ShGetObjectCode(const ShHandle handle,char * objCode)385 void ShGetObjectCode(const ShHandle handle, char* objCode)
386 {
387     if (!handle || !objCode)
388         return;
389 
390     TShHandleBase* base = static_cast<TShHandleBase*>(handle);
391     TCompiler* compiler = base->getAsCompiler();
392     if (!compiler) return;
393 
394     TInfoSink& infoSink = compiler->getInfoSink();
395     strcpy(objCode, infoSink.obj.c_str());
396 }
397 
ShGetVariableInfo(const ShHandle handle,ShShaderInfo varType,int index,size_t * length,int * size,sh::GLenum * type,ShPrecisionType * precision,int * staticUse,char * name,char * mappedName)398 void ShGetVariableInfo(const ShHandle handle,
399                        ShShaderInfo varType,
400                        int index,
401                        size_t* length,
402                        int* size,
403                        sh::GLenum* type,
404                        ShPrecisionType* precision,
405                        int* staticUse,
406                        char* name,
407                        char* mappedName)
408 {
409     if (!handle || !size || !type || !precision || !staticUse || !name)
410         return;
411     ASSERT((varType == SH_ACTIVE_ATTRIBUTES) ||
412            (varType == SH_ACTIVE_UNIFORMS) ||
413            (varType == SH_VARYINGS));
414 
415     TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
416     TCompiler* compiler = base->getAsCompiler();
417     if (compiler == 0)
418         return;
419 
420     const sh::ShaderVariable *varInfo = GetVariable(compiler, varType, index);
421     if (!varInfo)
422     {
423         return;
424     }
425 
426     if (length) *length = varInfo->name.size();
427     *size = varInfo->elementCount();
428     *type = varInfo->type;
429     *precision = ConvertPrecision(varInfo->precision);
430     *staticUse = varInfo->staticUse ? 1 : 0;
431 
432     // This size must match that queried by
433     // SH_ACTIVE_UNIFORM_MAX_LENGTH, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, SH_VARYING_MAX_LENGTH
434     // in ShGetInfo, below.
435     size_t variableLength = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec());
436     ASSERT(CheckVariableMaxLengths(handle, variableLength));
437     strncpy(name, varInfo->name.c_str(), variableLength);
438     name[variableLength - 1] = 0;
439     if (mappedName)
440     {
441         // This size must match that queried by
442         // SH_MAPPED_NAME_MAX_LENGTH in ShGetInfo, below.
443         size_t maxMappedNameLength = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec());
444         ASSERT(CheckMappedNameMaxLength(handle, maxMappedNameLength));
445         strncpy(mappedName, varInfo->mappedName.c_str(), maxMappedNameLength);
446         mappedName[maxMappedNameLength - 1] = 0;
447     }
448 }
449 
ShGetNameHashingEntry(const ShHandle handle,int index,char * name,char * hashedName)450 void ShGetNameHashingEntry(const ShHandle handle,
451                            int index,
452                            char* name,
453                            char* hashedName)
454 {
455     if (!handle || !name || !hashedName || index < 0)
456         return;
457 
458     TShHandleBase* base = static_cast<TShHandleBase*>(handle);
459     TCompiler* compiler = base->getAsCompiler();
460     if (!compiler) return;
461 
462     const NameMap& nameMap = compiler->getNameMap();
463     if (index >= static_cast<int>(nameMap.size()))
464         return;
465 
466     NameMap::const_iterator it = nameMap.begin();
467     for (int i = 0; i < index; ++i)
468         ++it;
469 
470     size_t len = it->first.length() + 1;
471     size_t max_len = 0;
472     ShGetInfo(handle, SH_NAME_MAX_LENGTH, &max_len);
473     if (len > max_len) {
474         ASSERT(false);
475         len = max_len;
476     }
477     strncpy(name, it->first.c_str(), len);
478     // To be on the safe side in case the source is longer than expected.
479     name[len - 1] = '\0';
480 
481     len = it->second.length() + 1;
482     max_len = 0;
483     ShGetInfo(handle, SH_HASHED_NAME_MAX_LENGTH, &max_len);
484     if (len > max_len) {
485         ASSERT(false);
486         len = max_len;
487     }
488     strncpy(hashedName, it->second.c_str(), len);
489     // To be on the safe side in case the source is longer than expected.
490     hashedName[len - 1] = '\0';
491 }
492 
ShGetUniforms(const ShHandle handle)493 const std::vector<sh::Uniform> *ShGetUniforms(const ShHandle handle)
494 {
495     return GetShaderVariables<sh::Uniform>(handle, SHADERVAR_UNIFORM);
496 }
497 
ShGetVaryings(const ShHandle handle)498 const std::vector<sh::Varying> *ShGetVaryings(const ShHandle handle)
499 {
500     return GetShaderVariables<sh::Varying>(handle, SHADERVAR_VARYING);
501 }
502 
ShGetAttributes(const ShHandle handle)503 const std::vector<sh::Attribute> *ShGetAttributes(const ShHandle handle)
504 {
505     return GetShaderVariables<sh::Attribute>(handle, SHADERVAR_ATTRIBUTE);
506 }
507 
ShGetOutputVariables(const ShHandle handle)508 const std::vector<sh::Attribute> *ShGetOutputVariables(const ShHandle handle)
509 {
510     return GetShaderVariables<sh::Attribute>(handle, SHADERVAR_OUTPUTVARIABLE);
511 }
512 
ShGetInterfaceBlocks(const ShHandle handle)513 const std::vector<sh::InterfaceBlock> *ShGetInterfaceBlocks(const ShHandle handle)
514 {
515     return GetShaderVariables<sh::InterfaceBlock>(handle, SHADERVAR_INTERFACEBLOCK);
516 }
517 
ShCheckVariablesWithinPackingLimits(int maxVectors,ShVariableInfo * varInfoArray,size_t varInfoArraySize)518 int ShCheckVariablesWithinPackingLimits(
519     int maxVectors, ShVariableInfo* varInfoArray, size_t varInfoArraySize)
520 {
521     if (varInfoArraySize == 0)
522         return 1;
523     ASSERT(varInfoArray);
524     std::vector<sh::ShaderVariable> variables;
525     for (size_t ii = 0; ii < varInfoArraySize; ++ii)
526     {
527         sh::ShaderVariable var(varInfoArray[ii].type, varInfoArray[ii].size);
528         variables.push_back(var);
529     }
530     VariablePacker packer;
531     return packer.CheckVariablesWithinPackingLimits(maxVectors, variables) ? 1 : 0;
532 }
533 
ShGetInterfaceBlockRegister(const ShHandle handle,const char * interfaceBlockName,unsigned int * indexOut)534 bool ShGetInterfaceBlockRegister(const ShHandle handle,
535                                  const char *interfaceBlockName,
536                                  unsigned int *indexOut)
537 {
538     if (!handle || !interfaceBlockName || !indexOut)
539     {
540         return false;
541     }
542 
543     TShHandleBase* base = static_cast<TShHandleBase*>(handle);
544     TranslatorHLSL* translator = base->getAsTranslatorHLSL();
545     if (!translator)
546     {
547         return false;
548     }
549 
550     if (!translator->hasInterfaceBlock(interfaceBlockName))
551     {
552         return false;
553     }
554 
555     *indexOut = translator->getInterfaceBlockRegister(interfaceBlockName);
556     return true;
557 }
558 
ShGetUniformRegister(const ShHandle handle,const char * uniformName,unsigned int * indexOut)559 bool ShGetUniformRegister(const ShHandle handle,
560                           const char *uniformName,
561                           unsigned int *indexOut)
562 {
563     if (!handle || !uniformName || !indexOut)
564     {
565         return false;
566     }
567 
568     TShHandleBase* base = static_cast<TShHandleBase*>(handle);
569     TranslatorHLSL* translator = base->getAsTranslatorHLSL();
570     if (!translator)
571     {
572         return false;
573     }
574 
575     if (!translator->hasUniform(uniformName))
576     {
577         return false;
578     }
579 
580     *indexOut = translator->getUniformRegister(uniformName);
581     return true;
582 }
583