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