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 #ifdef ANGLE_ENABLE_HLSL
18 #include "compiler/translator/TranslatorHLSL.h"
19 #endif // ANGLE_ENABLE_HLSL
20 #include "compiler/translator/VariablePacker.h"
21 #include "angle_gl.h"
22
23 namespace sh
24 {
25
26 namespace
27 {
28
29 bool isInitialized = false;
30
31 //
32 // This is the platform independent interface between an OGL driver
33 // and the shading language compiler.
34 //
35
36 template <typename VarT>
37 const std::vector<VarT> *GetVariableList(const TCompiler *compiler);
38
39 template <>
GetVariableList(const TCompiler * compiler)40 const std::vector<Uniform> *GetVariableList(const TCompiler *compiler)
41 {
42 return &compiler->getUniforms();
43 }
44
45 template <>
GetVariableList(const TCompiler * compiler)46 const std::vector<Varying> *GetVariableList(const TCompiler *compiler)
47 {
48 switch (compiler->getShaderType())
49 {
50 case GL_VERTEX_SHADER:
51 return &compiler->getOutputVaryings();
52 case GL_FRAGMENT_SHADER:
53 return &compiler->getInputVaryings();
54 case GL_COMPUTE_SHADER:
55 ASSERT(compiler->getOutputVaryings().empty() && compiler->getInputVaryings().empty());
56 return &compiler->getOutputVaryings();
57 // Since geometry shaders have both input and output varyings, we shouldn't call GetVaryings
58 // on a geometry shader.
59 default:
60 return nullptr;
61 }
62 }
63
64 template <>
GetVariableList(const TCompiler * compiler)65 const std::vector<Attribute> *GetVariableList(const TCompiler *compiler)
66 {
67 return &compiler->getAttributes();
68 }
69
70 template <>
GetVariableList(const TCompiler * compiler)71 const std::vector<OutputVariable> *GetVariableList(const TCompiler *compiler)
72 {
73 return &compiler->getOutputVariables();
74 }
75
76 template <>
GetVariableList(const TCompiler * compiler)77 const std::vector<InterfaceBlock> *GetVariableList(const TCompiler *compiler)
78 {
79 return &compiler->getInterfaceBlocks();
80 }
81
GetCompilerFromHandle(ShHandle handle)82 TCompiler *GetCompilerFromHandle(ShHandle handle)
83 {
84 if (!handle)
85 {
86 return nullptr;
87 }
88
89 TShHandleBase *base = static_cast<TShHandleBase *>(handle);
90 return base->getAsCompiler();
91 }
92
93 template <typename VarT>
GetShaderVariables(const ShHandle handle)94 const std::vector<VarT> *GetShaderVariables(const ShHandle handle)
95 {
96 TCompiler *compiler = GetCompilerFromHandle(handle);
97 if (!compiler)
98 {
99 return nullptr;
100 }
101
102 return GetVariableList<VarT>(compiler);
103 }
104
105 #ifdef ANGLE_ENABLE_HLSL
GetTranslatorHLSLFromHandle(ShHandle handle)106 TranslatorHLSL *GetTranslatorHLSLFromHandle(ShHandle handle)
107 {
108 if (!handle)
109 return nullptr;
110 TShHandleBase *base = static_cast<TShHandleBase *>(handle);
111 return base->getAsTranslatorHLSL();
112 }
113 #endif // ANGLE_ENABLE_HLSL
114
GetGeometryShaderPrimitiveTypeEnum(sh::TLayoutPrimitiveType primitiveType)115 GLenum GetGeometryShaderPrimitiveTypeEnum(sh::TLayoutPrimitiveType primitiveType)
116 {
117 switch (primitiveType)
118 {
119 case EptPoints:
120 return GL_POINTS;
121 case EptLines:
122 return GL_LINES;
123 case EptLinesAdjacency:
124 return GL_LINES_ADJACENCY_EXT;
125 case EptTriangles:
126 return GL_TRIANGLES;
127 case EptTrianglesAdjacency:
128 return GL_TRIANGLES_ADJACENCY_EXT;
129
130 case EptLineStrip:
131 return GL_LINE_STRIP;
132 case EptTriangleStrip:
133 return GL_TRIANGLE_STRIP;
134
135 case EptUndefined:
136 return GL_INVALID_VALUE;
137
138 default:
139 UNREACHABLE();
140 return GL_INVALID_VALUE;
141 }
142 }
143
144 } // anonymous namespace
145
146 //
147 // Driver must call this first, once, before doing any other compiler operations.
148 // Subsequent calls to this function are no-op.
149 //
Initialize()150 bool Initialize()
151 {
152 if (!isInitialized)
153 {
154 isInitialized = InitProcess();
155 }
156 return isInitialized;
157 }
158
159 //
160 // Cleanup symbol tables
161 //
Finalize()162 bool Finalize()
163 {
164 if (isInitialized)
165 {
166 DetachProcess();
167 isInitialized = false;
168 }
169 return true;
170 }
171
172 //
173 // Initialize built-in resources with minimum expected values.
174 //
InitBuiltInResources(ShBuiltInResources * resources)175 void InitBuiltInResources(ShBuiltInResources *resources)
176 {
177 // Make comparable.
178 memset(resources, 0, sizeof(*resources));
179
180 // Constants.
181 resources->MaxVertexAttribs = 8;
182 resources->MaxVertexUniformVectors = 128;
183 resources->MaxVaryingVectors = 8;
184 resources->MaxVertexTextureImageUnits = 0;
185 resources->MaxCombinedTextureImageUnits = 8;
186 resources->MaxTextureImageUnits = 8;
187 resources->MaxFragmentUniformVectors = 16;
188 resources->MaxDrawBuffers = 1;
189
190 // Extensions.
191 resources->OES_standard_derivatives = 0;
192 resources->OES_EGL_image_external = 0;
193 resources->OES_EGL_image_external_essl3 = 0;
194 resources->NV_EGL_stream_consumer_external = 0;
195 resources->ARB_texture_rectangle = 0;
196 resources->EXT_blend_func_extended = 0;
197 resources->EXT_draw_buffers = 0;
198 resources->EXT_frag_depth = 0;
199 resources->EXT_shader_texture_lod = 0;
200 resources->WEBGL_debug_shader_precision = 0;
201 resources->EXT_shader_framebuffer_fetch = 0;
202 resources->NV_shader_framebuffer_fetch = 0;
203 resources->ARM_shader_framebuffer_fetch = 0;
204 resources->OVR_multiview = 0;
205 resources->EXT_YUV_target = 0;
206 resources->OES_geometry_shader = 0;
207
208 resources->NV_draw_buffers = 0;
209
210 // Disable highp precision in fragment shader by default.
211 resources->FragmentPrecisionHigh = 0;
212
213 // GLSL ES 3.0 constants.
214 resources->MaxVertexOutputVectors = 16;
215 resources->MaxFragmentInputVectors = 15;
216 resources->MinProgramTexelOffset = -8;
217 resources->MaxProgramTexelOffset = 7;
218
219 // Extensions constants.
220 resources->MaxDualSourceDrawBuffers = 0;
221
222 resources->MaxViewsOVR = 4;
223
224 // Disable name hashing by default.
225 resources->HashFunction = nullptr;
226
227 resources->ArrayIndexClampingStrategy = SH_CLAMP_WITH_CLAMP_INTRINSIC;
228
229 resources->MaxExpressionComplexity = 256;
230 resources->MaxCallStackDepth = 256;
231 resources->MaxFunctionParameters = 1024;
232
233 // ES 3.1 Revision 4, 7.2 Built-in Constants
234
235 // ES 3.1, Revision 4, 8.13 Texture minification
236 // "The value of MIN_PROGRAM_TEXTURE_GATHER_OFFSET must be less than or equal to the value of
237 // MIN_PROGRAM_TEXEL_OFFSET. The value of MAX_PROGRAM_TEXTURE_GATHER_OFFSET must be greater than
238 // or equal to the value of MAX_PROGRAM_TEXEL_OFFSET"
239 resources->MinProgramTextureGatherOffset = -8;
240 resources->MaxProgramTextureGatherOffset = 7;
241
242 resources->MaxImageUnits = 4;
243 resources->MaxVertexImageUniforms = 0;
244 resources->MaxFragmentImageUniforms = 0;
245 resources->MaxComputeImageUniforms = 4;
246 resources->MaxCombinedImageUniforms = 4;
247
248 resources->MaxUniformLocations = 1024;
249
250 resources->MaxCombinedShaderOutputResources = 4;
251
252 resources->MaxComputeWorkGroupCount[0] = 65535;
253 resources->MaxComputeWorkGroupCount[1] = 65535;
254 resources->MaxComputeWorkGroupCount[2] = 65535;
255 resources->MaxComputeWorkGroupSize[0] = 128;
256 resources->MaxComputeWorkGroupSize[1] = 128;
257 resources->MaxComputeWorkGroupSize[2] = 64;
258 resources->MaxComputeUniformComponents = 512;
259 resources->MaxComputeTextureImageUnits = 16;
260
261 resources->MaxComputeAtomicCounters = 8;
262 resources->MaxComputeAtomicCounterBuffers = 1;
263
264 resources->MaxVertexAtomicCounters = 0;
265 resources->MaxFragmentAtomicCounters = 0;
266 resources->MaxCombinedAtomicCounters = 8;
267 resources->MaxAtomicCounterBindings = 1;
268
269 resources->MaxVertexAtomicCounterBuffers = 0;
270 resources->MaxFragmentAtomicCounterBuffers = 0;
271 resources->MaxCombinedAtomicCounterBuffers = 1;
272 resources->MaxAtomicCounterBufferSize = 32;
273
274 resources->MaxUniformBufferBindings = 32;
275 resources->MaxShaderStorageBufferBindings = 4;
276
277 resources->MaxGeometryUniformComponents = 1024;
278 resources->MaxGeometryUniformBlocks = 12;
279 resources->MaxGeometryInputComponents = 64;
280 resources->MaxGeometryOutputComponents = 64;
281 resources->MaxGeometryOutputVertices = 256;
282 resources->MaxGeometryTotalOutputComponents = 1024;
283 resources->MaxGeometryTextureImageUnits = 16;
284 resources->MaxGeometryAtomicCounterBuffers = 0;
285 resources->MaxGeometryAtomicCounters = 0;
286 resources->MaxGeometryShaderStorageBlocks = 0;
287 resources->MaxGeometryShaderInvocations = 32;
288 resources->MaxGeometryImageUniforms = 0;
289 }
290
291 //
292 // Driver calls these to create and destroy compiler objects.
293 //
ConstructCompiler(sh::GLenum type,ShShaderSpec spec,ShShaderOutput output,const ShBuiltInResources * resources)294 ShHandle ConstructCompiler(sh::GLenum type,
295 ShShaderSpec spec,
296 ShShaderOutput output,
297 const ShBuiltInResources *resources)
298 {
299 TShHandleBase *base = static_cast<TShHandleBase *>(ConstructCompiler(type, spec, output));
300 if (base == nullptr)
301 {
302 return 0;
303 }
304
305 TCompiler *compiler = base->getAsCompiler();
306 if (compiler == nullptr)
307 {
308 return 0;
309 }
310
311 // Generate built-in symbol table.
312 if (!compiler->Init(*resources))
313 {
314 Destruct(base);
315 return 0;
316 }
317
318 return reinterpret_cast<void *>(base);
319 }
320
Destruct(ShHandle handle)321 void Destruct(ShHandle handle)
322 {
323 if (handle == 0)
324 return;
325
326 TShHandleBase *base = static_cast<TShHandleBase *>(handle);
327
328 if (base->getAsCompiler())
329 DeleteCompiler(base->getAsCompiler());
330 }
331
GetBuiltInResourcesString(const ShHandle handle)332 const std::string &GetBuiltInResourcesString(const ShHandle handle)
333 {
334 TCompiler *compiler = GetCompilerFromHandle(handle);
335 ASSERT(compiler);
336 return compiler->getBuiltInResourcesString();
337 }
338
339 //
340 // Do an actual compile on the given strings. The result is left
341 // in the given compile object.
342 //
343 // Return: The return value of ShCompile is really boolean, indicating
344 // success or failure.
345 //
Compile(const ShHandle handle,const char * const shaderStrings[],size_t numStrings,ShCompileOptions compileOptions)346 bool Compile(const ShHandle handle,
347 const char *const shaderStrings[],
348 size_t numStrings,
349 ShCompileOptions compileOptions)
350 {
351 TCompiler *compiler = GetCompilerFromHandle(handle);
352 ASSERT(compiler);
353
354 return compiler->compile(shaderStrings, numStrings, compileOptions);
355 }
356
ClearResults(const ShHandle handle)357 void ClearResults(const ShHandle handle)
358 {
359 TCompiler *compiler = GetCompilerFromHandle(handle);
360 ASSERT(compiler);
361 compiler->clearResults();
362 }
363
GetShaderVersion(const ShHandle handle)364 int GetShaderVersion(const ShHandle handle)
365 {
366 TCompiler *compiler = GetCompilerFromHandle(handle);
367 ASSERT(compiler);
368 return compiler->getShaderVersion();
369 }
370
GetShaderOutputType(const ShHandle handle)371 ShShaderOutput GetShaderOutputType(const ShHandle handle)
372 {
373 TCompiler *compiler = GetCompilerFromHandle(handle);
374 ASSERT(compiler);
375 return compiler->getOutputType();
376 }
377
378 //
379 // Return any compiler log of messages for the application.
380 //
GetInfoLog(const ShHandle handle)381 const std::string &GetInfoLog(const ShHandle handle)
382 {
383 TCompiler *compiler = GetCompilerFromHandle(handle);
384 ASSERT(compiler);
385
386 TInfoSink &infoSink = compiler->getInfoSink();
387 return infoSink.info.str();
388 }
389
390 //
391 // Return any object code.
392 //
GetObjectCode(const ShHandle handle)393 const std::string &GetObjectCode(const ShHandle handle)
394 {
395 TCompiler *compiler = GetCompilerFromHandle(handle);
396 ASSERT(compiler);
397
398 TInfoSink &infoSink = compiler->getInfoSink();
399 return infoSink.obj.str();
400 }
401
GetNameHashingMap(const ShHandle handle)402 const std::map<std::string, std::string> *GetNameHashingMap(const ShHandle handle)
403 {
404 TCompiler *compiler = GetCompilerFromHandle(handle);
405 ASSERT(compiler);
406 return &(compiler->getNameMap());
407 }
408
GetUniforms(const ShHandle handle)409 const std::vector<Uniform> *GetUniforms(const ShHandle handle)
410 {
411 return GetShaderVariables<Uniform>(handle);
412 }
413
GetInputVaryings(const ShHandle handle)414 const std::vector<Varying> *GetInputVaryings(const ShHandle handle)
415 {
416 TCompiler *compiler = GetCompilerFromHandle(handle);
417 if (compiler == nullptr)
418 {
419 return nullptr;
420 }
421 return &compiler->getInputVaryings();
422 }
423
GetOutputVaryings(const ShHandle handle)424 const std::vector<Varying> *GetOutputVaryings(const ShHandle handle)
425 {
426 TCompiler *compiler = GetCompilerFromHandle(handle);
427 if (compiler == nullptr)
428 {
429 return nullptr;
430 }
431 return &compiler->getOutputVaryings();
432 }
433
GetVaryings(const ShHandle handle)434 const std::vector<Varying> *GetVaryings(const ShHandle handle)
435 {
436 return GetShaderVariables<Varying>(handle);
437 }
438
GetAttributes(const ShHandle handle)439 const std::vector<Attribute> *GetAttributes(const ShHandle handle)
440 {
441 return GetShaderVariables<Attribute>(handle);
442 }
443
GetOutputVariables(const ShHandle handle)444 const std::vector<OutputVariable> *GetOutputVariables(const ShHandle handle)
445 {
446 return GetShaderVariables<OutputVariable>(handle);
447 }
448
GetInterfaceBlocks(const ShHandle handle)449 const std::vector<InterfaceBlock> *GetInterfaceBlocks(const ShHandle handle)
450 {
451 return GetShaderVariables<InterfaceBlock>(handle);
452 }
453
GetUniformBlocks(const ShHandle handle)454 const std::vector<InterfaceBlock> *GetUniformBlocks(const ShHandle handle)
455 {
456 ASSERT(handle);
457 TShHandleBase *base = static_cast<TShHandleBase *>(handle);
458 TCompiler *compiler = base->getAsCompiler();
459 ASSERT(compiler);
460
461 return &compiler->getUniformBlocks();
462 }
463
GetShaderStorageBlocks(const ShHandle handle)464 const std::vector<InterfaceBlock> *GetShaderStorageBlocks(const ShHandle handle)
465 {
466 ASSERT(handle);
467 TShHandleBase *base = static_cast<TShHandleBase *>(handle);
468 TCompiler *compiler = base->getAsCompiler();
469 ASSERT(compiler);
470
471 return &compiler->getShaderStorageBlocks();
472 }
473
GetComputeShaderLocalGroupSize(const ShHandle handle)474 WorkGroupSize GetComputeShaderLocalGroupSize(const ShHandle handle)
475 {
476 ASSERT(handle);
477
478 TShHandleBase *base = static_cast<TShHandleBase *>(handle);
479 TCompiler *compiler = base->getAsCompiler();
480 ASSERT(compiler);
481
482 return compiler->getComputeShaderLocalSize();
483 }
484
GetVertexShaderNumViews(const ShHandle handle)485 int GetVertexShaderNumViews(const ShHandle handle)
486 {
487 ASSERT(handle);
488 TShHandleBase *base = static_cast<TShHandleBase *>(handle);
489 TCompiler *compiler = base->getAsCompiler();
490 ASSERT(compiler);
491
492 return compiler->getNumViews();
493 }
494
CheckVariablesWithinPackingLimits(int maxVectors,const std::vector<ShaderVariable> & variables)495 bool CheckVariablesWithinPackingLimits(int maxVectors, const std::vector<ShaderVariable> &variables)
496 {
497 return CheckVariablesInPackingLimits(maxVectors, variables);
498 }
499
GetUniformBlockRegister(const ShHandle handle,const std::string & uniformBlockName,unsigned int * indexOut)500 bool GetUniformBlockRegister(const ShHandle handle,
501 const std::string &uniformBlockName,
502 unsigned int *indexOut)
503 {
504 #ifdef ANGLE_ENABLE_HLSL
505 ASSERT(indexOut);
506
507 TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle);
508 ASSERT(translator);
509
510 if (!translator->hasUniformBlock(uniformBlockName))
511 {
512 return false;
513 }
514
515 *indexOut = translator->getUniformBlockRegister(uniformBlockName);
516 return true;
517 #else
518 return false;
519 #endif // ANGLE_ENABLE_HLSL
520 }
521
GetUniformRegisterMap(const ShHandle handle)522 const std::map<std::string, unsigned int> *GetUniformRegisterMap(const ShHandle handle)
523 {
524 #ifdef ANGLE_ENABLE_HLSL
525 TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle);
526 ASSERT(translator);
527
528 return translator->getUniformRegisterMap();
529 #else
530 return nullptr;
531 #endif // ANGLE_ENABLE_HLSL
532 }
533
GetGeometryShaderInputPrimitiveType(const ShHandle handle)534 GLenum GetGeometryShaderInputPrimitiveType(const ShHandle handle)
535 {
536 ASSERT(handle);
537
538 TShHandleBase *base = static_cast<TShHandleBase *>(handle);
539 TCompiler *compiler = base->getAsCompiler();
540 ASSERT(compiler);
541
542 return GetGeometryShaderPrimitiveTypeEnum(compiler->getGeometryShaderInputPrimitiveType());
543 }
544
GetGeometryShaderOutputPrimitiveType(const ShHandle handle)545 GLenum GetGeometryShaderOutputPrimitiveType(const ShHandle handle)
546 {
547 ASSERT(handle);
548
549 TShHandleBase *base = static_cast<TShHandleBase *>(handle);
550 TCompiler *compiler = base->getAsCompiler();
551 ASSERT(compiler);
552
553 return GetGeometryShaderPrimitiveTypeEnum(compiler->getGeometryShaderOutputPrimitiveType());
554 }
555
GetGeometryShaderInvocations(const ShHandle handle)556 int GetGeometryShaderInvocations(const ShHandle handle)
557 {
558 ASSERT(handle);
559
560 TShHandleBase *base = static_cast<TShHandleBase *>(handle);
561 TCompiler *compiler = base->getAsCompiler();
562 ASSERT(compiler);
563
564 return compiler->getGeometryShaderInvocations();
565 }
566
GetGeometryShaderMaxVertices(const ShHandle handle)567 int GetGeometryShaderMaxVertices(const ShHandle handle)
568 {
569 ASSERT(handle);
570
571 TShHandleBase *base = static_cast<TShHandleBase *>(handle);
572 TCompiler *compiler = base->getAsCompiler();
573 ASSERT(compiler);
574
575 return compiler->getGeometryShaderMaxVertices();
576 }
577
578 } // namespace sh
579