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
23namespace sh
24{
25
26namespace
27{
28
29bool isInitialized = false;
30
31//
32// This is the platform independent interface between an OGL driver
33// and the shading language compiler.
34//
35
36template <typename VarT>
37const std::vector<VarT> *GetVariableList(const TCompiler *compiler);
38
39template <>
40const std::vector<Uniform> *GetVariableList(const TCompiler *compiler)
41{
42 return &compiler->getUniforms();
43}
44
45template <>
46const 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
64template <>
65const std::vector<Attribute> *GetVariableList(const TCompiler *compiler)
66{
67 return &compiler->getAttributes();
68}
69
70template <>
71const std::vector<OutputVariable> *GetVariableList(const TCompiler *compiler)
72{
73 return &compiler->getOutputVariables();
74}
75
76template <>
77const std::vector<InterfaceBlock> *GetVariableList(const TCompiler *compiler)
78{
79 return &compiler->getInterfaceBlocks();
80}
81
82TCompiler *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
93template <typename VarT>
94const 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
106TranslatorHLSL *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
115GLenum 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//
148bool Initialize()
149{
150 if (!isInitialized)
151 {
152 isInitialized = InitProcess();
153 }
154 return isInitialized;
155}
156
157//
158// Cleanup symbol tables
159//
160bool 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//
173void 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//
295ShHandle 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
322void 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
333const 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//
347bool 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
358void ClearResults(const ShHandle handle)
359{
360 TCompiler *compiler = GetCompilerFromHandle(handle);
361 ASSERT(compiler);
362 compiler->clearResults();
363}
364
365int GetShaderVersion(const ShHandle handle)
366{
367 TCompiler *compiler = GetCompilerFromHandle(handle);
368 ASSERT(compiler);
369 return compiler->getShaderVersion();
370}
371
372ShShaderOutput 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//
382const 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//
394const 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
403const 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
410const std::vector<Uniform> *GetUniforms(const ShHandle handle)
411{
412 return GetShaderVariables<Uniform>(handle);
413}
414
415const 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
425const 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
435const std::vector<Varying> *GetVaryings(const ShHandle handle)
436{
437 return GetShaderVariables<Varying>(handle);
438}
439
440const std::vector<Attribute> *GetAttributes(const ShHandle handle)
441{
442 return GetShaderVariables<Attribute>(handle);
443}
444
445const std::vector<OutputVariable> *GetOutputVariables(const ShHandle handle)
446{
447 return GetShaderVariables<OutputVariable>(handle);
448}
449
450const std::vector<InterfaceBlock> *GetInterfaceBlocks(const ShHandle handle)
451{
452 return GetShaderVariables<InterfaceBlock>(handle);
453}
454
455const 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
465const 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
475WorkGroupSize 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
486int 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
496bool CheckVariablesWithinPackingLimits(int maxVectors, const std::vector<ShaderVariable> &variables)
497{
498 return CheckVariablesInPackingLimits(maxVectors, variables);
499}
500
501bool 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
523bool 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
545const 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
557unsigned 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
569unsigned 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
581const 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
593bool 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
604bool 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
615bool 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
626GLenum 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
637GLenum 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
648int 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
659int 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