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