|
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 |
|
19 // |
|
20 // This is the platform independent interface between an OGL driver |
|
21 // and the shading language compiler. |
|
22 // |
|
23 |
|
24 static bool checkActiveUniformAndAttribMaxLengths(const ShHandle handle, |
|
25 size_t expectedValue) |
|
26 { |
|
27 size_t activeUniformLimit = 0; |
|
28 ShGetInfo(handle, SH_ACTIVE_UNIFORM_MAX_LENGTH, &activeUniformLimit); |
|
29 size_t activeAttribLimit = 0; |
|
30 ShGetInfo(handle, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, &activeAttribLimit); |
|
31 return (expectedValue == activeUniformLimit && expectedValue == activeAttribLimit); |
|
32 } |
|
33 |
|
34 static bool checkMappedNameMaxLength(const ShHandle handle, size_t expectedValue) |
|
35 { |
|
36 size_t mappedNameMaxLength = 0; |
|
37 ShGetInfo(handle, SH_MAPPED_NAME_MAX_LENGTH, &mappedNameMaxLength); |
|
38 return (expectedValue == mappedNameMaxLength); |
|
39 } |
|
40 |
|
41 static void getVariableInfo(ShShaderInfo varType, |
|
42 const ShHandle handle, |
|
43 int index, |
|
44 size_t* length, |
|
45 int* size, |
|
46 ShDataType* type, |
|
47 char* name, |
|
48 char* mappedName) |
|
49 { |
|
50 if (!handle || !size || !type || !name) |
|
51 return; |
|
52 ASSERT((varType == SH_ACTIVE_ATTRIBUTES) || |
|
53 (varType == SH_ACTIVE_UNIFORMS)); |
|
54 |
|
55 TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle); |
|
56 TCompiler* compiler = base->getAsCompiler(); |
|
57 if (compiler == 0) |
|
58 return; |
|
59 |
|
60 const TVariableInfoList& varList = varType == SH_ACTIVE_ATTRIBUTES ? |
|
61 compiler->getAttribs() : compiler->getUniforms(); |
|
62 if (index < 0 || index >= static_cast<int>(varList.size())) |
|
63 return; |
|
64 |
|
65 const TVariableInfo& varInfo = varList[index]; |
|
66 if (length) *length = varInfo.name.size(); |
|
67 *size = varInfo.size; |
|
68 *type = varInfo.type; |
|
69 |
|
70 // This size must match that queried by |
|
71 // SH_ACTIVE_UNIFORM_MAX_LENGTH and SH_ACTIVE_ATTRIBUTE_MAX_LENGTH |
|
72 // in ShGetInfo, below. |
|
73 size_t activeUniformAndAttribLength = 1 + MAX_SYMBOL_NAME_LEN; |
|
74 ASSERT(checkActiveUniformAndAttribMaxLengths(handle, activeUniformAndAttribLength)); |
|
75 strncpy(name, varInfo.name.c_str(), activeUniformAndAttribLength); |
|
76 name[activeUniformAndAttribLength - 1] = 0; |
|
77 if (mappedName) { |
|
78 // This size must match that queried by |
|
79 // SH_MAPPED_NAME_MAX_LENGTH in ShGetInfo, below. |
|
80 size_t maxMappedNameLength = 1 + MAX_SYMBOL_NAME_LEN; |
|
81 ASSERT(checkMappedNameMaxLength(handle, maxMappedNameLength)); |
|
82 strncpy(mappedName, varInfo.mappedName.c_str(), maxMappedNameLength); |
|
83 mappedName[maxMappedNameLength - 1] = 0; |
|
84 } |
|
85 } |
|
86 |
|
87 // |
|
88 // Driver must call this first, once, before doing any other compiler operations. |
|
89 // Subsequent calls to this function are no-op. |
|
90 // |
|
91 int ShInitialize() |
|
92 { |
|
93 static const bool kInitialized = InitProcess(); |
|
94 return kInitialized ? 1 : 0; |
|
95 } |
|
96 |
|
97 // |
|
98 // Cleanup symbol tables |
|
99 // |
|
100 int ShFinalize() |
|
101 { |
|
102 DetachProcess(); |
|
103 return 1; |
|
104 } |
|
105 |
|
106 // |
|
107 // Initialize built-in resources with minimum expected values. |
|
108 // |
|
109 void ShInitBuiltInResources(ShBuiltInResources* resources) |
|
110 { |
|
111 // Constants. |
|
112 resources->MaxVertexAttribs = 8; |
|
113 resources->MaxVertexUniformVectors = 128; |
|
114 resources->MaxVaryingVectors = 8; |
|
115 resources->MaxVertexTextureImageUnits = 0; |
|
116 resources->MaxCombinedTextureImageUnits = 8; |
|
117 resources->MaxTextureImageUnits = 8; |
|
118 resources->MaxFragmentUniformVectors = 16; |
|
119 resources->MaxDrawBuffers = 1; |
|
120 |
|
121 // Extensions. |
|
122 resources->OES_standard_derivatives = 0; |
|
123 resources->OES_EGL_image_external = 0; |
|
124 resources->ARB_texture_rectangle = 0; |
|
125 resources->EXT_draw_buffers = 0; |
|
126 resources->EXT_frag_depth = 0; |
|
127 |
|
128 // Disable highp precision in fragment shader by default. |
|
129 resources->FragmentPrecisionHigh = 0; |
|
130 |
|
131 // Disable name hashing by default. |
|
132 resources->HashFunction = NULL; |
|
133 |
|
134 resources->ArrayIndexClampingStrategy = SH_CLAMP_WITH_CLAMP_INTRINSIC; |
|
135 } |
|
136 |
|
137 // |
|
138 // Driver calls these to create and destroy compiler objects. |
|
139 // |
|
140 ShHandle ShConstructCompiler(ShShaderType type, ShShaderSpec spec, |
|
141 ShShaderOutput output, |
|
142 const ShBuiltInResources* resources) |
|
143 { |
|
144 TShHandleBase* base = static_cast<TShHandleBase*>(ConstructCompiler(type, spec, output)); |
|
145 TCompiler* compiler = base->getAsCompiler(); |
|
146 if (compiler == 0) |
|
147 return 0; |
|
148 |
|
149 // Generate built-in symbol table. |
|
150 if (!compiler->Init(*resources)) { |
|
151 ShDestruct(base); |
|
152 return 0; |
|
153 } |
|
154 |
|
155 return reinterpret_cast<void*>(base); |
|
156 } |
|
157 |
|
158 void ShDestruct(ShHandle handle) |
|
159 { |
|
160 if (handle == 0) |
|
161 return; |
|
162 |
|
163 TShHandleBase* base = static_cast<TShHandleBase*>(handle); |
|
164 |
|
165 if (base->getAsCompiler()) |
|
166 DeleteCompiler(base->getAsCompiler()); |
|
167 } |
|
168 |
|
169 // |
|
170 // Do an actual compile on the given strings. The result is left |
|
171 // in the given compile object. |
|
172 // |
|
173 // Return: The return value of ShCompile is really boolean, indicating |
|
174 // success or failure. |
|
175 // |
|
176 int ShCompile( |
|
177 const ShHandle handle, |
|
178 const char* const shaderStrings[], |
|
179 size_t numStrings, |
|
180 int compileOptions) |
|
181 { |
|
182 if (handle == 0) |
|
183 return 0; |
|
184 |
|
185 TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle); |
|
186 TCompiler* compiler = base->getAsCompiler(); |
|
187 if (compiler == 0) |
|
188 return 0; |
|
189 |
|
190 bool success = compiler->compile(shaderStrings, numStrings, compileOptions); |
|
191 return success ? 1 : 0; |
|
192 } |
|
193 |
|
194 void ShGetInfo(const ShHandle handle, ShShaderInfo pname, size_t* params) |
|
195 { |
|
196 if (!handle || !params) |
|
197 return; |
|
198 |
|
199 TShHandleBase* base = static_cast<TShHandleBase*>(handle); |
|
200 TCompiler* compiler = base->getAsCompiler(); |
|
201 if (!compiler) return; |
|
202 |
|
203 switch(pname) |
|
204 { |
|
205 case SH_INFO_LOG_LENGTH: |
|
206 *params = compiler->getInfoSink().info.size() + 1; |
|
207 break; |
|
208 case SH_OBJECT_CODE_LENGTH: |
|
209 *params = compiler->getInfoSink().obj.size() + 1; |
|
210 break; |
|
211 case SH_ACTIVE_UNIFORMS: |
|
212 *params = compiler->getUniforms().size(); |
|
213 break; |
|
214 case SH_ACTIVE_UNIFORM_MAX_LENGTH: |
|
215 *params = 1 + MAX_SYMBOL_NAME_LEN; |
|
216 break; |
|
217 case SH_ACTIVE_ATTRIBUTES: |
|
218 *params = compiler->getAttribs().size(); |
|
219 break; |
|
220 case SH_ACTIVE_ATTRIBUTE_MAX_LENGTH: |
|
221 *params = 1 + MAX_SYMBOL_NAME_LEN; |
|
222 break; |
|
223 case SH_MAPPED_NAME_MAX_LENGTH: |
|
224 // Use longer length than MAX_SHORTENED_IDENTIFIER_SIZE to |
|
225 // handle array and struct dereferences. |
|
226 *params = 1 + MAX_SYMBOL_NAME_LEN; |
|
227 break; |
|
228 case SH_NAME_MAX_LENGTH: |
|
229 *params = 1 + MAX_SYMBOL_NAME_LEN; |
|
230 break; |
|
231 case SH_HASHED_NAME_MAX_LENGTH: |
|
232 if (compiler->getHashFunction() == NULL) { |
|
233 *params = 0; |
|
234 } else { |
|
235 // 64 bits hashing output requires 16 bytes for hex |
|
236 // representation. |
|
237 const char HashedNamePrefix[] = HASHED_NAME_PREFIX; |
|
238 *params = 16 + sizeof(HashedNamePrefix); |
|
239 } |
|
240 break; |
|
241 case SH_HASHED_NAMES_COUNT: |
|
242 *params = compiler->getNameMap().size(); |
|
243 break; |
|
244 default: UNREACHABLE(); |
|
245 } |
|
246 } |
|
247 |
|
248 // |
|
249 // Return any compiler log of messages for the application. |
|
250 // |
|
251 void ShGetInfoLog(const ShHandle handle, char* infoLog) |
|
252 { |
|
253 if (!handle || !infoLog) |
|
254 return; |
|
255 |
|
256 TShHandleBase* base = static_cast<TShHandleBase*>(handle); |
|
257 TCompiler* compiler = base->getAsCompiler(); |
|
258 if (!compiler) return; |
|
259 |
|
260 TInfoSink& infoSink = compiler->getInfoSink(); |
|
261 strcpy(infoLog, infoSink.info.c_str()); |
|
262 } |
|
263 |
|
264 // |
|
265 // Return any object code. |
|
266 // |
|
267 void ShGetObjectCode(const ShHandle handle, char* objCode) |
|
268 { |
|
269 if (!handle || !objCode) |
|
270 return; |
|
271 |
|
272 TShHandleBase* base = static_cast<TShHandleBase*>(handle); |
|
273 TCompiler* compiler = base->getAsCompiler(); |
|
274 if (!compiler) return; |
|
275 |
|
276 TInfoSink& infoSink = compiler->getInfoSink(); |
|
277 strcpy(objCode, infoSink.obj.c_str()); |
|
278 } |
|
279 |
|
280 void ShGetActiveAttrib(const ShHandle handle, |
|
281 int index, |
|
282 size_t* length, |
|
283 int* size, |
|
284 ShDataType* type, |
|
285 char* name, |
|
286 char* mappedName) |
|
287 { |
|
288 getVariableInfo(SH_ACTIVE_ATTRIBUTES, |
|
289 handle, index, length, size, type, name, mappedName); |
|
290 } |
|
291 |
|
292 void ShGetActiveUniform(const ShHandle handle, |
|
293 int index, |
|
294 size_t* length, |
|
295 int* size, |
|
296 ShDataType* type, |
|
297 char* name, |
|
298 char* mappedName) |
|
299 { |
|
300 getVariableInfo(SH_ACTIVE_UNIFORMS, |
|
301 handle, index, length, size, type, name, mappedName); |
|
302 } |
|
303 |
|
304 void ShGetNameHashingEntry(const ShHandle handle, |
|
305 int index, |
|
306 char* name, |
|
307 char* hashedName) |
|
308 { |
|
309 if (!handle || !name || !hashedName || index < 0) |
|
310 return; |
|
311 |
|
312 TShHandleBase* base = static_cast<TShHandleBase*>(handle); |
|
313 TCompiler* compiler = base->getAsCompiler(); |
|
314 if (!compiler) return; |
|
315 |
|
316 const NameMap& nameMap = compiler->getNameMap(); |
|
317 if (index >= static_cast<int>(nameMap.size())) |
|
318 return; |
|
319 |
|
320 NameMap::const_iterator it = nameMap.begin(); |
|
321 for (int i = 0; i < index; ++i) |
|
322 ++it; |
|
323 |
|
324 size_t len = it->first.length() + 1; |
|
325 size_t max_len = 0; |
|
326 ShGetInfo(handle, SH_NAME_MAX_LENGTH, &max_len); |
|
327 if (len > max_len) { |
|
328 ASSERT(false); |
|
329 len = max_len; |
|
330 } |
|
331 strncpy(name, it->first.c_str(), len); |
|
332 // To be on the safe side in case the source is longer than expected. |
|
333 name[len - 1] = '\0'; |
|
334 |
|
335 len = it->second.length() + 1; |
|
336 max_len = 0; |
|
337 ShGetInfo(handle, SH_HASHED_NAME_MAX_LENGTH, &max_len); |
|
338 if (len > max_len) { |
|
339 ASSERT(false); |
|
340 len = max_len; |
|
341 } |
|
342 strncpy(hashedName, it->second.c_str(), len); |
|
343 // To be on the safe side in case the source is longer than expected. |
|
344 hashedName[len - 1] = '\0'; |
|
345 } |
|
346 |
|
347 void ShGetInfoPointer(const ShHandle handle, ShShaderInfo pname, void** params) |
|
348 { |
|
349 if (!handle || !params) |
|
350 return; |
|
351 |
|
352 TShHandleBase* base = static_cast<TShHandleBase*>(handle); |
|
353 TranslatorHLSL* translator = base->getAsTranslatorHLSL(); |
|
354 if (!translator) return; |
|
355 |
|
356 switch(pname) |
|
357 { |
|
358 case SH_ACTIVE_UNIFORMS_ARRAY: |
|
359 *params = (void*)&translator->getUniforms(); |
|
360 break; |
|
361 default: UNREACHABLE(); |
|
362 } |
|
363 } |