blob: 45183b0f988103d036530db0e88efe4f99b1709d [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
2// Copyright (c) 2002-2010 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//
alokp@chromium.org774d7062010-07-21 18:55:45 +00008// Implement the top-level of interface to the compiler,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00009// as defined in ShaderLang.h
10//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000011
alokp@chromium.orgea0e1af2010-03-22 19:33:14 +000012#include "GLSLANG/ShaderLang.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000013
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000014#include "compiler/Initialize.h"
15#include "compiler/InitializeDll.h"
16#include "compiler/ParseHelper.h"
17#include "compiler/ShHandle.h"
18#include "compiler/SymbolTable.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000019
alokp@chromium.orge4249f02010-07-26 18:13:52 +000020static bool InitializeSymbolTable(
21 const TBuiltInStrings& builtInStrings,
22 EShLanguage language, EShSpec spec, const TBuiltInResource& resources,
23 TInfoSink& infoSink, TSymbolTable& symbolTable)
24{
25 TIntermediate intermediate(infoSink);
alokp@chromium.orgad771eb2010-09-07 17:36:23 +000026 TExtensionBehavior extBehavior;
27 TParseContext parseContext(symbolTable, extBehavior, intermediate, language, spec, infoSink);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000028
alokp@chromium.orge4249f02010-07-26 18:13:52 +000029 GlobalParseContext = &parseContext;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000030
alokp@chromium.orge4249f02010-07-26 18:13:52 +000031 setInitialState();
32
33 assert(symbolTable.isEmpty());
34 //
35 // Parse the built-ins. This should only happen once per
36 // language symbol table.
37 //
38 // Push the symbol table to give it an initial scope. This
39 // push should not have a corresponding pop, so that built-ins
40 // are preserved, and the test for an empty table fails.
41 //
42 symbolTable.push();
43
44 //Initialize the Preprocessor
45 if (InitPreprocessor())
46 {
47 infoSink.info.message(EPrefixInternalError, "Unable to intialize the Preprocessor");
48 return false;
49 }
50
51 for (TBuiltInStrings::const_iterator i = builtInStrings.begin(); i != builtInStrings.end(); ++i)
52 {
53 const char* builtInShaders[1];
54 int builtInLengths[1];
55
56 builtInShaders[0] = (*i).c_str();
57 builtInLengths[0] = (int) (*i).size();
58
59 if (PaParseStrings(const_cast<char**>(builtInShaders), builtInLengths, 1, parseContext) != 0)
60 {
61 infoSink.info.message(EPrefixInternalError, "Unable to parse built-ins");
62 return false;
63 }
64 }
65
66 IdentifyBuiltIns(language, spec, resources, symbolTable);
67
68 FinalizePreprocessor();
69
70 return true;
71}
72
73static bool GenerateBuiltInSymbolTable(
74 EShLanguage language, EShSpec spec, const TBuiltInResource& resources,
75 TInfoSink& infoSink, TSymbolTable& symbolTable)
76{
77 TBuiltIns builtIns;
78
79 builtIns.initialize(language, spec, resources);
80 return InitializeSymbolTable(builtIns.getBuiltInStrings(), language, spec, resources, infoSink, symbolTable);
81}
82
alokp@chromium.orgad771eb2010-09-07 17:36:23 +000083static void DefineExtensionMacros(const TExtensionBehavior& extBehavior)
84{
85 for (TExtensionBehavior::const_iterator iter = extBehavior.begin();
86 iter != extBehavior.end(); ++iter) {
87 PredefineIntMacro(iter->first.c_str(), 1);
88 }
89}
90
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000091//
92// This is the platform independent interface between an OGL driver
alokp@chromium.org774d7062010-07-21 18:55:45 +000093// and the shading language compiler.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000094//
95
96//
97// Driver must call this first, once, before doing any other
alokp@chromium.org774d7062010-07-21 18:55:45 +000098// compiler operations.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000099//
100int ShInitialize()
101{
alokp@chromium.org34b99cd2010-07-27 18:37:55 +0000102 if (!InitProcess())
103 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000104
alokp@chromium.org34b99cd2010-07-27 18:37:55 +0000105 return 1;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000106}
107
108//
alokp@chromium.org94a86ad2010-08-25 20:02:11 +0000109// Cleanup symbol tables
110//
111int ShFinalize()
112{
113 if (!DetachProcess())
114 return 0;
115
116 return 1;
117}
118
119//
120// Initialize built-in resources with minimum expected values.
121//
122void ShInitBuiltInResource(TBuiltInResource* resources)
123{
124 // Constants.
125 resources->MaxVertexAttribs = 8;
126 resources->MaxVertexUniformVectors = 128;
127 resources->MaxVaryingVectors = 8;
128 resources->MaxVertexTextureImageUnits = 0;
129 resources->MaxCombinedTextureImageUnits = 8;
130 resources->MaxTextureImageUnits = 8;
131 resources->MaxFragmentUniformVectors = 16;
132 resources->MaxDrawBuffers = 1;
133
134 // Extensions.
135 resources->OES_standard_derivatives = 0;
136}
137
138//
alokp@chromium.org774d7062010-07-21 18:55:45 +0000139// Driver calls these to create and destroy compiler objects.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000140//
alokp@chromium.orge4249f02010-07-26 18:13:52 +0000141ShHandle ShConstructCompiler(EShLanguage language, EShSpec spec, const TBuiltInResource* resources)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000142{
143 if (!InitThread())
144 return 0;
145
alokp@chromium.org29cd91a2010-07-16 19:30:45 +0000146 TShHandleBase* base = static_cast<TShHandleBase*>(ConstructCompiler(language, spec));
alokp@chromium.orge4249f02010-07-26 18:13:52 +0000147 TCompiler* compiler = base->getAsCompiler();
148 if (compiler == 0)
149 return 0;
150
151 // Generate built-in symbol table.
152 if (!GenerateBuiltInSymbolTable(language, spec, *resources, compiler->getInfoSink(), compiler->getSymbolTable())) {
153 ShDestruct(base);
154 return 0;
155 }
alokp@chromium.orgad771eb2010-09-07 17:36:23 +0000156 InitExtensionBehavior(*resources, compiler->getExtensionBehavior());
alokp@chromium.orge4249f02010-07-26 18:13:52 +0000157
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000158 return reinterpret_cast<void*>(base);
159}
160
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000161void ShDestruct(ShHandle handle)
162{
163 if (handle == 0)
164 return;
165
166 TShHandleBase* base = static_cast<TShHandleBase*>(handle);
167
168 if (base->getAsCompiler())
169 DeleteCompiler(base->getAsCompiler());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000170}
171
172//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000173// Do an actual compile on the given strings. The result is left
174// in the given compile object.
175//
176// Return: The return value of ShCompile is really boolean, indicating
177// success or failure.
178//
179int ShCompile(
180 const ShHandle handle,
181 const char* const shaderStrings[],
182 const int numStrings,
alokp@chromium.org7beea402010-09-15 21:18:34 +0000183 int compileOptions)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000184{
185 if (!InitThread())
186 return 0;
187
188 if (handle == 0)
189 return 0;
190
191 TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
192 TCompiler* compiler = base->getAsCompiler();
193 if (compiler == 0)
194 return 0;
195
196 GlobalPoolAllocator.push();
alokp@chromium.orge4249f02010-07-26 18:13:52 +0000197 TInfoSink& infoSink = compiler->getInfoSink();
alokp@chromium.org76b82082010-03-24 17:59:39 +0000198 infoSink.info.erase();
199 infoSink.debug.erase();
200 infoSink.obj.erase();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000201
202 if (numStrings == 0)
203 return 1;
204
alokp@chromium.org76b82082010-03-24 17:59:39 +0000205 TIntermediate intermediate(infoSink);
alokp@chromium.orge4249f02010-07-26 18:13:52 +0000206 TSymbolTable& symbolTable = compiler->getSymbolTable();
alokp@chromium.orgad771eb2010-09-07 17:36:23 +0000207 const TExtensionBehavior& extBehavior = compiler->getExtensionBehavior();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000208
alokp@chromium.orgad771eb2010-09-07 17:36:23 +0000209 TParseContext parseContext(symbolTable, extBehavior, intermediate,
210 compiler->getLanguage(), compiler->getSpec(), infoSink);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000211 GlobalParseContext = &parseContext;
alokp@chromium.orge4249f02010-07-26 18:13:52 +0000212
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000213 setInitialState();
214
alokp@chromium.orge4249f02010-07-26 18:13:52 +0000215 InitPreprocessor();
alokp@chromium.orgad771eb2010-09-07 17:36:23 +0000216 DefineExtensionMacros(extBehavior);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000217 //
218 // Parse the application's shaders. All the following symbol table
219 // work will be throw-away, so push a new allocation scope that can
220 // be thrown away, then push a scope for the current shader's globals.
221 //
222 bool success = true;
alokp@chromium.orge4249f02010-07-26 18:13:52 +0000223
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000224 symbolTable.push();
225 if (!symbolTable.atGlobalLevel())
226 parseContext.infoSink.info.message(EPrefixInternalError, "Wrong symbol table level");
227
alokp@chromium.org7beea402010-09-15 21:18:34 +0000228 if (PaParseStrings(const_cast<char**>(shaderStrings), 0, numStrings, parseContext))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000229 success = false;
230
231 if (success && parseContext.treeRoot) {
alokp@chromium.org7beea402010-09-15 21:18:34 +0000232 success = intermediate.postProcess(parseContext.treeRoot, parseContext.language);
233 if (success) {
234 if (compileOptions & EShOptIntermediateTree)
235 intermediate.outputTree(parseContext.treeRoot);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000236
alokp@chromium.org7beea402010-09-15 21:18:34 +0000237 //
238 // Call the machine dependent compiler
239 //
240 if (compileOptions & EShOptObjectCode)
241 success = compiler->compile(parseContext.treeRoot);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000242
alokp@chromium.org7beea402010-09-15 21:18:34 +0000243 // TODO(alokp): Extract attributes and uniforms.
244 //if (compileOptions & EShOptAttribsUniforms)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000245 }
246 } else if (!success) {
247 parseContext.infoSink.info.prefix(EPrefixError);
248 parseContext.infoSink.info << parseContext.numErrors << " compilation errors. No code generated.\n\n";
249 success = false;
alokp@chromium.org7beea402010-09-15 21:18:34 +0000250 if (compileOptions & EShOptIntermediateTree)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000251 intermediate.outputTree(parseContext.treeRoot);
daniel@transgaming.combb2e9632010-04-13 19:53:50 +0000252 } else if (!parseContext.treeRoot) {
253 parseContext.error(1, "Unexpected end of file.", "", "");
254 parseContext.infoSink.info << parseContext.numErrors << " compilation errors. No code generated.\n\n";
255 success = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000256 }
257
258 intermediate.remove(parseContext.treeRoot);
259
260 //
261 // Ensure symbol table is returned to the built-in level,
262 // throwing away all but the built-ins.
263 //
alokp@chromium.orge4249f02010-07-26 18:13:52 +0000264 while (!symbolTable.atBuiltInLevel())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000265 symbolTable.pop();
266
267 FinalizePreprocessor();
268 //
269 // Throw away all the temporary memory used by the compilation process.
270 //
271 GlobalPoolAllocator.pop();
272
273 return success ? 1 : 0;
274}
275
alokp@chromium.org7beea402010-09-15 21:18:34 +0000276void ShGetInfo(const ShHandle handle, EShInfo pname, int* params)
277{
278 if (!handle || !params)
279 return;
280
281 TShHandleBase* base = static_cast<TShHandleBase*>(handle);
282 TCompiler* compiler = base->getAsCompiler();
283 if (!compiler) return;
284
285 switch(pname)
286 {
287 case SH_INFO_LOG_LENGTH:
288 *params = compiler->getInfoSink().info.size() + 1;
289 break;
290 case SH_OBJECT_CODE_LENGTH:
291 *params = compiler->getInfoSink().obj.size() + 1;
292 break;
293 case SH_ACTIVE_UNIFORMS:
294 UNIMPLEMENTED();
295 break;
296 case SH_ACTIVE_UNIFORM_MAX_LENGTH:
297 UNIMPLEMENTED();
298 break;
299 case SH_ACTIVE_ATTRIBUTES:
300 UNIMPLEMENTED();
301 break;
302 case SH_ACTIVE_ATTRIBUTE_MAX_LENGTH:
303 UNIMPLEMENTED();
304 break;
305
306 default: UNREACHABLE();
307 }
308}
309
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000310//
alokp@chromium.org774d7062010-07-21 18:55:45 +0000311// Return any compiler log of messages for the application.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000312//
alokp@chromium.org7beea402010-09-15 21:18:34 +0000313void ShGetInfoLog(const ShHandle handle, char* infoLog)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000314{
alokp@chromium.org7beea402010-09-15 21:18:34 +0000315 if (!handle || !infoLog)
316 return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000317
318 TShHandleBase* base = static_cast<TShHandleBase*>(handle);
alokp@chromium.org7beea402010-09-15 21:18:34 +0000319 TCompiler* compiler = base->getAsCompiler();
320 if (!compiler) return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000321
alokp@chromium.org7beea402010-09-15 21:18:34 +0000322 TInfoSink& infoSink = compiler->getInfoSink();
323 strcpy(infoLog, infoSink.info.c_str());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000324}
325
326//
alokp@chromium.org774d7062010-07-21 18:55:45 +0000327// Return any object code.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000328//
alokp@chromium.org7beea402010-09-15 21:18:34 +0000329void ShGetObjectCode(const ShHandle handle, char* objCode)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000330{
alokp@chromium.org7beea402010-09-15 21:18:34 +0000331 if (!handle || !objCode)
332 return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000333
334 TShHandleBase* base = static_cast<TShHandleBase*>(handle);
alokp@chromium.org7beea402010-09-15 21:18:34 +0000335 TCompiler* compiler = base->getAsCompiler();
336 if (!compiler) return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000337
alokp@chromium.org7beea402010-09-15 21:18:34 +0000338 TInfoSink& infoSink = compiler->getInfoSink();
339 strcpy(objCode, infoSink.obj.c_str());
340}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000341
alokp@chromium.org7beea402010-09-15 21:18:34 +0000342void ShGetActiveAttrib(const ShHandle handle,
343 int index,
344 int* length,
345 int* size,
346 EShDataType* type,
347 char* name)
348{
349 UNIMPLEMENTED();
350}
351
352void ShGetActiveUniform(const ShHandle handle,
353 int index,
354 int* length,
355 int* size,
356 EShDataType* type,
357 char* name)
358{
359 UNIMPLEMENTED();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000360}