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