• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2002 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 "angle_gl.h"
21 #include "compiler/translator/VariablePacker.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         default:
137             UNREACHABLE();
138             return GL_INVALID_VALUE;
139     }
140 }
141 
142 }  // anonymous namespace
143 
144 //
145 // Driver must call this first, once, before doing any other compiler operations.
146 // Subsequent calls to this function are no-op.
147 //
Initialize()148 bool Initialize()
149 {
150     if (!isInitialized)
151     {
152         isInitialized = InitProcess();
153     }
154     return isInitialized;
155 }
156 
157 //
158 // Cleanup symbol tables
159 //
Finalize()160 bool Finalize()
161 {
162     if (isInitialized)
163     {
164         DetachProcess();
165         isInitialized = false;
166     }
167     return true;
168 }
169 
170 //
171 // Initialize built-in resources with minimum expected values.
172 //
InitBuiltInResources(ShBuiltInResources * resources)173 void InitBuiltInResources(ShBuiltInResources *resources)
174 {
175     // Make comparable.
176     memset(resources, 0, sizeof(*resources));
177 
178     // Constants.
179     resources->MaxVertexAttribs             = 8;
180     resources->MaxVertexUniformVectors      = 128;
181     resources->MaxVaryingVectors            = 8;
182     resources->MaxVertexTextureImageUnits   = 0;
183     resources->MaxCombinedTextureImageUnits = 8;
184     resources->MaxTextureImageUnits         = 8;
185     resources->MaxFragmentUniformVectors    = 16;
186     resources->MaxDrawBuffers               = 1;
187 
188     // Extensions.
189     resources->OES_standard_derivatives                 = 0;
190     resources->OES_EGL_image_external                   = 0;
191     resources->OES_EGL_image_external_essl3             = 0;
192     resources->NV_EGL_stream_consumer_external          = 0;
193     resources->ARB_texture_rectangle                    = 0;
194     resources->EXT_blend_func_extended                  = 0;
195     resources->EXT_draw_buffers                         = 0;
196     resources->EXT_frag_depth                           = 0;
197     resources->EXT_shader_texture_lod                   = 0;
198     resources->WEBGL_debug_shader_precision             = 0;
199     resources->EXT_shader_framebuffer_fetch             = 0;
200     resources->NV_shader_framebuffer_fetch              = 0;
201     resources->ARM_shader_framebuffer_fetch             = 0;
202     resources->OVR_multiview                            = 0;
203     resources->OVR_multiview2                           = 0;
204     resources->EXT_YUV_target                           = 0;
205     resources->EXT_geometry_shader                      = 0;
206     resources->OES_texture_storage_multisample_2d_array = 0;
207     resources->OES_texture_3D                           = 0;
208     resources->ANGLE_texture_multisample                = 0;
209     resources->ANGLE_multi_draw                         = 0;
210     resources->ANGLE_base_vertex_base_instance          = 0;
211 
212     resources->NV_draw_buffers = 0;
213 
214     // Disable highp precision in fragment shader by default.
215     resources->FragmentPrecisionHigh = 0;
216 
217     // GLSL ES 3.0 constants.
218     resources->MaxVertexOutputVectors  = 16;
219     resources->MaxFragmentInputVectors = 15;
220     resources->MinProgramTexelOffset   = -8;
221     resources->MaxProgramTexelOffset   = 7;
222 
223     // Extensions constants.
224     resources->MaxDualSourceDrawBuffers = 0;
225 
226     resources->MaxViewsOVR = 4;
227 
228     // Disable name hashing by default.
229     resources->HashFunction = nullptr;
230 
231     resources->ArrayIndexClampingStrategy = SH_CLAMP_WITH_CLAMP_INTRINSIC;
232 
233     resources->MaxExpressionComplexity = 256;
234     resources->MaxCallStackDepth       = 256;
235     resources->MaxFunctionParameters   = 1024;
236 
237     // ES 3.1 Revision 4, 7.2 Built-in Constants
238 
239     // ES 3.1, Revision 4, 8.13 Texture minification
240     // "The value of MIN_PROGRAM_TEXTURE_GATHER_OFFSET must be less than or equal to the value of
241     // MIN_PROGRAM_TEXEL_OFFSET. The value of MAX_PROGRAM_TEXTURE_GATHER_OFFSET must be greater than
242     // or equal to the value of MAX_PROGRAM_TEXEL_OFFSET"
243     resources->MinProgramTextureGatherOffset = -8;
244     resources->MaxProgramTextureGatherOffset = 7;
245 
246     resources->MaxImageUnits            = 4;
247     resources->MaxVertexImageUniforms   = 0;
248     resources->MaxFragmentImageUniforms = 0;
249     resources->MaxComputeImageUniforms  = 4;
250     resources->MaxCombinedImageUniforms = 4;
251 
252     resources->MaxUniformLocations = 1024;
253 
254     resources->MaxCombinedShaderOutputResources = 4;
255 
256     resources->MaxComputeWorkGroupCount[0] = 65535;
257     resources->MaxComputeWorkGroupCount[1] = 65535;
258     resources->MaxComputeWorkGroupCount[2] = 65535;
259     resources->MaxComputeWorkGroupSize[0]  = 128;
260     resources->MaxComputeWorkGroupSize[1]  = 128;
261     resources->MaxComputeWorkGroupSize[2]  = 64;
262     resources->MaxComputeUniformComponents = 512;
263     resources->MaxComputeTextureImageUnits = 16;
264 
265     resources->MaxComputeAtomicCounters       = 8;
266     resources->MaxComputeAtomicCounterBuffers = 1;
267 
268     resources->MaxVertexAtomicCounters   = 0;
269     resources->MaxFragmentAtomicCounters = 0;
270     resources->MaxCombinedAtomicCounters = 8;
271     resources->MaxAtomicCounterBindings  = 1;
272 
273     resources->MaxVertexAtomicCounterBuffers   = 0;
274     resources->MaxFragmentAtomicCounterBuffers = 0;
275     resources->MaxCombinedAtomicCounterBuffers = 1;
276     resources->MaxAtomicCounterBufferSize      = 32;
277 
278     resources->MaxUniformBufferBindings       = 32;
279     resources->MaxShaderStorageBufferBindings = 4;
280 
281     resources->MaxGeometryUniformComponents     = 1024;
282     resources->MaxGeometryUniformBlocks         = 12;
283     resources->MaxGeometryInputComponents       = 64;
284     resources->MaxGeometryOutputComponents      = 64;
285     resources->MaxGeometryOutputVertices        = 256;
286     resources->MaxGeometryTotalOutputComponents = 1024;
287     resources->MaxGeometryTextureImageUnits     = 16;
288     resources->MaxGeometryAtomicCounterBuffers  = 0;
289     resources->MaxGeometryAtomicCounters        = 0;
290     resources->MaxGeometryShaderStorageBlocks   = 0;
291     resources->MaxGeometryShaderInvocations     = 32;
292     resources->MaxGeometryImageUniforms         = 0;
293 }
294 
295 //
296 // Driver calls these to create and destroy compiler objects.
297 //
ConstructCompiler(sh::GLenum type,ShShaderSpec spec,ShShaderOutput output,const ShBuiltInResources * resources)298 ShHandle ConstructCompiler(sh::GLenum type,
299                            ShShaderSpec spec,
300                            ShShaderOutput output,
301                            const ShBuiltInResources *resources)
302 {
303     TShHandleBase *base = static_cast<TShHandleBase *>(ConstructCompiler(type, spec, output));
304     if (base == nullptr)
305     {
306         return 0;
307     }
308 
309     TCompiler *compiler = base->getAsCompiler();
310     if (compiler == nullptr)
311     {
312         return 0;
313     }
314 
315     // Generate built-in symbol table.
316     if (!compiler->Init(*resources))
317     {
318         Destruct(base);
319         return 0;
320     }
321 
322     return base;
323 }
324 
Destruct(ShHandle handle)325 void Destruct(ShHandle handle)
326 {
327     if (handle == 0)
328         return;
329 
330     TShHandleBase *base = static_cast<TShHandleBase *>(handle);
331 
332     if (base->getAsCompiler())
333         DeleteCompiler(base->getAsCompiler());
334 }
335 
GetBuiltInResourcesString(const ShHandle handle)336 const std::string &GetBuiltInResourcesString(const ShHandle handle)
337 {
338     TCompiler *compiler = GetCompilerFromHandle(handle);
339     ASSERT(compiler);
340     return compiler->getBuiltInResourcesString();
341 }
342 
343 //
344 // Do an actual compile on the given strings.  The result is left
345 // in the given compile object.
346 //
347 // Return:  The return value of ShCompile is really boolean, indicating
348 // success or failure.
349 //
Compile(const ShHandle handle,const char * const shaderStrings[],size_t numStrings,ShCompileOptions compileOptions)350 bool Compile(const ShHandle handle,
351              const char *const shaderStrings[],
352              size_t numStrings,
353              ShCompileOptions compileOptions)
354 {
355     TCompiler *compiler = GetCompilerFromHandle(handle);
356     ASSERT(compiler);
357 
358     return compiler->compile(shaderStrings, numStrings, compileOptions);
359 }
360 
ClearResults(const ShHandle handle)361 void ClearResults(const ShHandle handle)
362 {
363     TCompiler *compiler = GetCompilerFromHandle(handle);
364     ASSERT(compiler);
365     compiler->clearResults();
366 }
367 
GetShaderVersion(const ShHandle handle)368 int GetShaderVersion(const ShHandle handle)
369 {
370     TCompiler *compiler = GetCompilerFromHandle(handle);
371     ASSERT(compiler);
372     return compiler->getShaderVersion();
373 }
374 
GetShaderOutputType(const ShHandle handle)375 ShShaderOutput GetShaderOutputType(const ShHandle handle)
376 {
377     TCompiler *compiler = GetCompilerFromHandle(handle);
378     ASSERT(compiler);
379     return compiler->getOutputType();
380 }
381 
382 //
383 // Return any compiler log of messages for the application.
384 //
GetInfoLog(const ShHandle handle)385 const std::string &GetInfoLog(const ShHandle handle)
386 {
387     TCompiler *compiler = GetCompilerFromHandle(handle);
388     ASSERT(compiler);
389 
390     TInfoSink &infoSink = compiler->getInfoSink();
391     return infoSink.info.str();
392 }
393 
394 //
395 // Return any object code.
396 //
GetObjectCode(const ShHandle handle)397 const std::string &GetObjectCode(const ShHandle handle)
398 {
399     TCompiler *compiler = GetCompilerFromHandle(handle);
400     ASSERT(compiler);
401 
402     TInfoSink &infoSink = compiler->getInfoSink();
403     return infoSink.obj.str();
404 }
405 
GetNameHashingMap(const ShHandle handle)406 const std::map<std::string, std::string> *GetNameHashingMap(const ShHandle handle)
407 {
408     TCompiler *compiler = GetCompilerFromHandle(handle);
409     ASSERT(compiler);
410     return &(compiler->getNameMap());
411 }
412 
GetUniforms(const ShHandle handle)413 const std::vector<Uniform> *GetUniforms(const ShHandle handle)
414 {
415     return GetShaderVariables<Uniform>(handle);
416 }
417 
GetInputVaryings(const ShHandle handle)418 const std::vector<Varying> *GetInputVaryings(const ShHandle handle)
419 {
420     TCompiler *compiler = GetCompilerFromHandle(handle);
421     if (compiler == nullptr)
422     {
423         return nullptr;
424     }
425     return &compiler->getInputVaryings();
426 }
427 
GetOutputVaryings(const ShHandle handle)428 const std::vector<Varying> *GetOutputVaryings(const ShHandle handle)
429 {
430     TCompiler *compiler = GetCompilerFromHandle(handle);
431     if (compiler == nullptr)
432     {
433         return nullptr;
434     }
435     return &compiler->getOutputVaryings();
436 }
437 
GetVaryings(const ShHandle handle)438 const std::vector<Varying> *GetVaryings(const ShHandle handle)
439 {
440     return GetShaderVariables<Varying>(handle);
441 }
442 
GetAttributes(const ShHandle handle)443 const std::vector<Attribute> *GetAttributes(const ShHandle handle)
444 {
445     return GetShaderVariables<Attribute>(handle);
446 }
447 
GetOutputVariables(const ShHandle handle)448 const std::vector<OutputVariable> *GetOutputVariables(const ShHandle handle)
449 {
450     return GetShaderVariables<OutputVariable>(handle);
451 }
452 
GetInterfaceBlocks(const ShHandle handle)453 const std::vector<InterfaceBlock> *GetInterfaceBlocks(const ShHandle handle)
454 {
455     return GetShaderVariables<InterfaceBlock>(handle);
456 }
457 
GetUniformBlocks(const ShHandle handle)458 const std::vector<InterfaceBlock> *GetUniformBlocks(const ShHandle handle)
459 {
460     ASSERT(handle);
461     TShHandleBase *base = static_cast<TShHandleBase *>(handle);
462     TCompiler *compiler = base->getAsCompiler();
463     ASSERT(compiler);
464 
465     return &compiler->getUniformBlocks();
466 }
467 
GetShaderStorageBlocks(const ShHandle handle)468 const std::vector<InterfaceBlock> *GetShaderStorageBlocks(const ShHandle handle)
469 {
470     ASSERT(handle);
471     TShHandleBase *base = static_cast<TShHandleBase *>(handle);
472     TCompiler *compiler = base->getAsCompiler();
473     ASSERT(compiler);
474 
475     return &compiler->getShaderStorageBlocks();
476 }
477 
GetComputeShaderLocalGroupSize(const ShHandle handle)478 WorkGroupSize GetComputeShaderLocalGroupSize(const ShHandle handle)
479 {
480     ASSERT(handle);
481 
482     TShHandleBase *base = static_cast<TShHandleBase *>(handle);
483     TCompiler *compiler = base->getAsCompiler();
484     ASSERT(compiler);
485 
486     return compiler->getComputeShaderLocalSize();
487 }
488 
GetVertexShaderNumViews(const ShHandle handle)489 int GetVertexShaderNumViews(const ShHandle handle)
490 {
491     ASSERT(handle);
492     TShHandleBase *base = static_cast<TShHandleBase *>(handle);
493     TCompiler *compiler = base->getAsCompiler();
494     ASSERT(compiler);
495 
496     return compiler->getNumViews();
497 }
498 
CheckVariablesWithinPackingLimits(int maxVectors,const std::vector<ShaderVariable> & variables)499 bool CheckVariablesWithinPackingLimits(int maxVectors, const std::vector<ShaderVariable> &variables)
500 {
501     return CheckVariablesInPackingLimits(maxVectors, variables);
502 }
503 
GetShaderStorageBlockRegister(const ShHandle handle,const std::string & shaderStorageBlockName,unsigned int * indexOut)504 bool GetShaderStorageBlockRegister(const ShHandle handle,
505                                    const std::string &shaderStorageBlockName,
506                                    unsigned int *indexOut)
507 {
508 #ifdef ANGLE_ENABLE_HLSL
509     ASSERT(indexOut);
510 
511     TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle);
512     ASSERT(translator);
513 
514     if (!translator->hasShaderStorageBlock(shaderStorageBlockName))
515     {
516         return false;
517     }
518 
519     *indexOut = translator->getShaderStorageBlockRegister(shaderStorageBlockName);
520     return true;
521 #else
522     return false;
523 #endif  // ANGLE_ENABLE_HLSL
524 }
525 
GetUniformBlockRegister(const ShHandle handle,const std::string & uniformBlockName,unsigned int * indexOut)526 bool GetUniformBlockRegister(const ShHandle handle,
527                              const std::string &uniformBlockName,
528                              unsigned int *indexOut)
529 {
530 #ifdef ANGLE_ENABLE_HLSL
531     ASSERT(indexOut);
532 
533     TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle);
534     ASSERT(translator);
535 
536     if (!translator->hasUniformBlock(uniformBlockName))
537     {
538         return false;
539     }
540 
541     *indexOut = translator->getUniformBlockRegister(uniformBlockName);
542     return true;
543 #else
544     return false;
545 #endif  // ANGLE_ENABLE_HLSL
546 }
547 
GetUniformRegisterMap(const ShHandle handle)548 const std::map<std::string, unsigned int> *GetUniformRegisterMap(const ShHandle handle)
549 {
550 #ifdef ANGLE_ENABLE_HLSL
551     TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle);
552     ASSERT(translator);
553 
554     return translator->getUniformRegisterMap();
555 #else
556     return nullptr;
557 #endif  // ANGLE_ENABLE_HLSL
558 }
559 
GetReadonlyImage2DRegisterIndex(const ShHandle handle)560 unsigned int GetReadonlyImage2DRegisterIndex(const ShHandle handle)
561 {
562 #ifdef ANGLE_ENABLE_HLSL
563     TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle);
564     ASSERT(translator);
565 
566     return translator->getReadonlyImage2DRegisterIndex();
567 #else
568     return 0;
569 #endif  // ANGLE_ENABLE_HLSL
570 }
571 
GetImage2DRegisterIndex(const ShHandle handle)572 unsigned int GetImage2DRegisterIndex(const ShHandle handle)
573 {
574 #ifdef ANGLE_ENABLE_HLSL
575     TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle);
576     ASSERT(translator);
577 
578     return translator->getImage2DRegisterIndex();
579 #else
580     return 0;
581 #endif  // ANGLE_ENABLE_HLSL
582 }
583 
GetUsedImage2DFunctionNames(const ShHandle handle)584 const std::set<std::string> *GetUsedImage2DFunctionNames(const ShHandle handle)
585 {
586 #ifdef ANGLE_ENABLE_HLSL
587     TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle);
588     ASSERT(translator);
589 
590     return translator->getUsedImage2DFunctionNames();
591 #else
592     return nullptr;
593 #endif  // ANGLE_ENABLE_HLSL
594 }
595 
HasValidGeometryShaderInputPrimitiveType(const ShHandle handle)596 bool HasValidGeometryShaderInputPrimitiveType(const ShHandle handle)
597 {
598     ASSERT(handle);
599 
600     TShHandleBase *base = static_cast<TShHandleBase *>(handle);
601     TCompiler *compiler = base->getAsCompiler();
602     ASSERT(compiler);
603 
604     return compiler->getGeometryShaderInputPrimitiveType() != EptUndefined;
605 }
606 
HasValidGeometryShaderOutputPrimitiveType(const ShHandle handle)607 bool HasValidGeometryShaderOutputPrimitiveType(const ShHandle handle)
608 {
609     ASSERT(handle);
610 
611     TShHandleBase *base = static_cast<TShHandleBase *>(handle);
612     TCompiler *compiler = base->getAsCompiler();
613     ASSERT(compiler);
614 
615     return compiler->getGeometryShaderOutputPrimitiveType() != EptUndefined;
616 }
617 
HasValidGeometryShaderMaxVertices(const ShHandle handle)618 bool HasValidGeometryShaderMaxVertices(const ShHandle handle)
619 {
620     ASSERT(handle);
621 
622     TShHandleBase *base = static_cast<TShHandleBase *>(handle);
623     TCompiler *compiler = base->getAsCompiler();
624     ASSERT(compiler);
625 
626     return compiler->getGeometryShaderMaxVertices() >= 0;
627 }
628 
GetGeometryShaderInputPrimitiveType(const ShHandle handle)629 GLenum GetGeometryShaderInputPrimitiveType(const ShHandle handle)
630 {
631     ASSERT(handle);
632 
633     TShHandleBase *base = static_cast<TShHandleBase *>(handle);
634     TCompiler *compiler = base->getAsCompiler();
635     ASSERT(compiler);
636 
637     return GetGeometryShaderPrimitiveTypeEnum(compiler->getGeometryShaderInputPrimitiveType());
638 }
639 
GetGeometryShaderOutputPrimitiveType(const ShHandle handle)640 GLenum GetGeometryShaderOutputPrimitiveType(const ShHandle handle)
641 {
642     ASSERT(handle);
643 
644     TShHandleBase *base = static_cast<TShHandleBase *>(handle);
645     TCompiler *compiler = base->getAsCompiler();
646     ASSERT(compiler);
647 
648     return GetGeometryShaderPrimitiveTypeEnum(compiler->getGeometryShaderOutputPrimitiveType());
649 }
650 
GetGeometryShaderInvocations(const ShHandle handle)651 int GetGeometryShaderInvocations(const ShHandle handle)
652 {
653     ASSERT(handle);
654 
655     TShHandleBase *base = static_cast<TShHandleBase *>(handle);
656     TCompiler *compiler = base->getAsCompiler();
657     ASSERT(compiler);
658 
659     return compiler->getGeometryShaderInvocations();
660 }
661 
GetGeometryShaderMaxVertices(const ShHandle handle)662 int GetGeometryShaderMaxVertices(const ShHandle handle)
663 {
664     ASSERT(handle);
665 
666     TShHandleBase *base = static_cast<TShHandleBase *>(handle);
667     TCompiler *compiler = base->getAsCompiler();
668     ASSERT(compiler);
669 
670     int maxVertices = compiler->getGeometryShaderMaxVertices();
671     ASSERT(maxVertices >= 0);
672     return maxVertices;
673 }
674 
675 }  // namespace sh
676