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