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