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