1 //
2 // Copyright 2014 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 // Compiler.cpp: implements the gl::Compiler class.
8 
9 #include "libANGLE/Compiler.h"
10 
11 #include "common/debug.h"
12 #include "libANGLE/Context.h"
13 #include "libANGLE/Display.h"
14 #include "libANGLE/State.h"
15 #include "libANGLE/renderer/CompilerImpl.h"
16 #include "libANGLE/renderer/GLImplFactory.h"
17 
18 namespace gl
19 {
20 
21 namespace
22 {
23 
24 // To know when to call sh::Initialize and sh::Finalize.
25 size_t gActiveCompilers = 0;
26 
SelectShaderSpec(GLint majorVersion,GLint minorVersion,bool isWebGL,EGLenum clientType)27 ShShaderSpec SelectShaderSpec(GLint majorVersion,
28                               GLint minorVersion,
29                               bool isWebGL,
30                               EGLenum clientType)
31 {
32     // For Desktop GL
33     if (clientType == EGL_OPENGL_API)
34     {
35         return SH_GL_COMPATIBILITY_SPEC;
36     }
37 
38     if (majorVersion >= 3)
39     {
40         if (minorVersion == 1)
41         {
42             return isWebGL ? SH_WEBGL3_SPEC : SH_GLES3_1_SPEC;
43         }
44         else
45         {
46             return isWebGL ? SH_WEBGL2_SPEC : SH_GLES3_SPEC;
47         }
48     }
49 
50     // GLES1 emulation: Use GLES3 shader spec.
51     if (!isWebGL && majorVersion == 1)
52     {
53         return SH_GLES3_SPEC;
54     }
55 
56     return isWebGL ? SH_WEBGL_SPEC : SH_GLES2_SPEC;
57 }
58 
59 }  // anonymous namespace
60 
Compiler(rx::GLImplFactory * implFactory,const State & state,egl::Display * display)61 Compiler::Compiler(rx::GLImplFactory *implFactory, const State &state, egl::Display *display)
62     : mImplementation(implFactory->createCompiler()),
63       mSpec(SelectShaderSpec(state.getClientMajorVersion(),
64                              state.getClientMinorVersion(),
65                              state.getExtensions().webglCompatibility,
66                              state.getClientType())),
67       mOutputType(mImplementation->getTranslatorOutputType()),
68       mResources()
69 {
70     // TODO(http://anglebug.com/3819): Update for GL version specific validation
71     ASSERT(state.getClientMajorVersion() == 1 || state.getClientMajorVersion() == 2 ||
72            state.getClientMajorVersion() == 3 || state.getClientMajorVersion() == 4);
73 
74     const gl::Caps &caps             = state.getCaps();
75     const gl::Extensions &extensions = state.getExtensions();
76 
77     {
78         std::lock_guard<std::mutex> lock(display->getDisplayGlobalMutex());
79         if (gActiveCompilers == 0)
80         {
81             sh::Initialize();
82         }
83         ++gActiveCompilers;
84     }
85 
86     sh::InitBuiltInResources(&mResources);
87     mResources.MaxVertexAttribs             = caps.maxVertexAttributes;
88     mResources.MaxVertexUniformVectors      = caps.maxVertexUniformVectors;
89     mResources.MaxVaryingVectors            = caps.maxVaryingVectors;
90     mResources.MaxVertexTextureImageUnits   = caps.maxShaderTextureImageUnits[ShaderType::Vertex];
91     mResources.MaxCombinedTextureImageUnits = caps.maxCombinedTextureImageUnits;
92     mResources.MaxTextureImageUnits         = caps.maxShaderTextureImageUnits[ShaderType::Fragment];
93     mResources.MaxFragmentUniformVectors    = caps.maxFragmentUniformVectors;
94     mResources.MaxDrawBuffers               = caps.maxDrawBuffers;
95     mResources.OES_standard_derivatives     = extensions.standardDerivativesOES;
96     mResources.EXT_draw_buffers             = extensions.drawBuffers;
97     mResources.EXT_shader_texture_lod       = extensions.shaderTextureLOD;
98     mResources.EXT_shader_non_constant_global_initializers =
99         extensions.shaderNonConstGlobalInitializersEXT;
100     mResources.OES_EGL_image_external                = extensions.eglImageExternalOES;
101     mResources.OES_EGL_image_external_essl3          = extensions.eglImageExternalEssl3OES;
102     mResources.NV_EGL_stream_consumer_external       = extensions.eglStreamConsumerExternalNV;
103     mResources.NV_shader_noperspective_interpolation = extensions.noperspectiveInterpolationNV;
104     mResources.ARB_texture_rectangle                 = extensions.textureRectangle;
105     mResources.EXT_gpu_shader5                       = extensions.gpuShader5EXT;
106     mResources.OES_texture_storage_multisample_2d_array =
107         extensions.textureStorageMultisample2DArrayOES;
108     mResources.OES_texture_3D                  = extensions.texture3DOES;
109     mResources.ANGLE_texture_multisample       = extensions.textureMultisample;
110     mResources.ANGLE_multi_draw                = extensions.multiDraw;
111     mResources.ANGLE_base_vertex_base_instance = extensions.baseVertexBaseInstance;
112     mResources.APPLE_clip_distance             = extensions.clipDistanceAPPLE;
113     // OES_shader_multisample_interpolation
114     mResources.OES_shader_multisample_interpolation = extensions.multisampleInterpolationOES;
115     mResources.OES_shader_image_atomic              = extensions.shaderImageAtomicOES;
116     // TODO: use shader precision caps to determine if high precision is supported?
117     mResources.FragmentPrecisionHigh = 1;
118     mResources.EXT_frag_depth        = extensions.fragDepth;
119 
120     // OVR_multiview state
121     mResources.OVR_multiview = extensions.multiview;
122 
123     // OVR_multiview2 state
124     mResources.OVR_multiview2 = extensions.multiview2;
125     mResources.MaxViewsOVR    = extensions.maxViews;
126 
127     // EXT_multisampled_render_to_texture and EXT_multisampled_render_to_texture2
128     mResources.EXT_multisampled_render_to_texture  = extensions.multisampledRenderToTexture;
129     mResources.EXT_multisampled_render_to_texture2 = extensions.multisampledRenderToTexture2;
130 
131     // WEBGL_video_texture
132     mResources.WEBGL_video_texture = extensions.webglVideoTexture;
133 
134     // OES_texture_cube_map_array
135     mResources.OES_texture_cube_map_array = extensions.textureCubeMapArrayOES;
136     mResources.EXT_texture_cube_map_array = extensions.textureCubeMapArrayEXT;
137 
138     // EXT_shadow_samplers
139     mResources.EXT_shadow_samplers = extensions.shadowSamplersEXT;
140 
141     // OES_texture_buffer
142     mResources.OES_texture_buffer = extensions.textureBufferOES;
143     mResources.EXT_texture_buffer = extensions.textureBufferEXT;
144 
145     // GLSL ES 3.0 constants
146     mResources.MaxVertexOutputVectors  = caps.maxVertexOutputComponents / 4;
147     mResources.MaxFragmentInputVectors = caps.maxFragmentInputComponents / 4;
148     mResources.MinProgramTexelOffset   = caps.minProgramTexelOffset;
149     mResources.MaxProgramTexelOffset   = caps.maxProgramTexelOffset;
150 
151     // EXT_blend_func_extended
152     mResources.EXT_blend_func_extended  = extensions.blendFuncExtended;
153     mResources.MaxDualSourceDrawBuffers = extensions.maxDualSourceDrawBuffers;
154 
155     // APPLE_clip_distance/EXT_clip_cull_distance
156     mResources.MaxClipDistances = caps.maxClipDistances;
157 
158     // GLSL ES 3.1 constants
159     mResources.MaxProgramTextureGatherOffset    = caps.maxProgramTextureGatherOffset;
160     mResources.MinProgramTextureGatherOffset    = caps.minProgramTextureGatherOffset;
161     mResources.MaxImageUnits                    = caps.maxImageUnits;
162     mResources.MaxVertexImageUniforms           = caps.maxShaderImageUniforms[ShaderType::Vertex];
163     mResources.MaxFragmentImageUniforms         = caps.maxShaderImageUniforms[ShaderType::Fragment];
164     mResources.MaxComputeImageUniforms          = caps.maxShaderImageUniforms[ShaderType::Compute];
165     mResources.MaxCombinedImageUniforms         = caps.maxCombinedImageUniforms;
166     mResources.MaxCombinedShaderOutputResources = caps.maxCombinedShaderOutputResources;
167     mResources.MaxUniformLocations              = caps.maxUniformLocations;
168 
169     for (size_t index = 0u; index < 3u; ++index)
170     {
171         mResources.MaxComputeWorkGroupCount[index] = caps.maxComputeWorkGroupCount[index];
172         mResources.MaxComputeWorkGroupSize[index]  = caps.maxComputeWorkGroupSize[index];
173     }
174 
175     mResources.MaxComputeUniformComponents = caps.maxShaderUniformComponents[ShaderType::Compute];
176     mResources.MaxComputeTextureImageUnits = caps.maxShaderTextureImageUnits[ShaderType::Compute];
177 
178     mResources.MaxComputeAtomicCounters = caps.maxShaderAtomicCounters[ShaderType::Compute];
179     mResources.MaxComputeAtomicCounterBuffers =
180         caps.maxShaderAtomicCounterBuffers[ShaderType::Compute];
181 
182     mResources.MaxVertexAtomicCounters   = caps.maxShaderAtomicCounters[ShaderType::Vertex];
183     mResources.MaxFragmentAtomicCounters = caps.maxShaderAtomicCounters[ShaderType::Fragment];
184     mResources.MaxCombinedAtomicCounters = caps.maxCombinedAtomicCounters;
185     mResources.MaxAtomicCounterBindings  = caps.maxAtomicCounterBufferBindings;
186     mResources.MaxVertexAtomicCounterBuffers =
187         caps.maxShaderAtomicCounterBuffers[ShaderType::Vertex];
188     mResources.MaxFragmentAtomicCounterBuffers =
189         caps.maxShaderAtomicCounterBuffers[ShaderType::Fragment];
190     mResources.MaxCombinedAtomicCounterBuffers = caps.maxCombinedAtomicCounterBuffers;
191     mResources.MaxAtomicCounterBufferSize      = caps.maxAtomicCounterBufferSize;
192 
193     mResources.MaxUniformBufferBindings       = caps.maxUniformBufferBindings;
194     mResources.MaxShaderStorageBufferBindings = caps.maxShaderStorageBufferBindings;
195 
196     // Needed by point size clamping workaround
197     mResources.MaxPointSize = caps.maxAliasedPointSize;
198 
199     if (state.getClientMajorVersion() == 2 && !extensions.drawBuffers)
200     {
201         mResources.MaxDrawBuffers = 1;
202     }
203 
204     // Geometry Shader constants
205     mResources.EXT_geometry_shader          = extensions.geometryShader;
206     mResources.MaxGeometryUniformComponents = caps.maxShaderUniformComponents[ShaderType::Geometry];
207     mResources.MaxGeometryUniformBlocks     = caps.maxShaderUniformBlocks[ShaderType::Geometry];
208     mResources.MaxGeometryInputComponents   = caps.maxGeometryInputComponents;
209     mResources.MaxGeometryOutputComponents  = caps.maxGeometryOutputComponents;
210     mResources.MaxGeometryOutputVertices    = caps.maxGeometryOutputVertices;
211     mResources.MaxGeometryTotalOutputComponents = caps.maxGeometryTotalOutputComponents;
212     mResources.MaxGeometryTextureImageUnits = caps.maxShaderTextureImageUnits[ShaderType::Geometry];
213 
214     mResources.MaxGeometryAtomicCounterBuffers =
215         caps.maxShaderAtomicCounterBuffers[ShaderType::Geometry];
216     mResources.MaxGeometryAtomicCounters      = caps.maxShaderAtomicCounters[ShaderType::Geometry];
217     mResources.MaxGeometryShaderStorageBlocks = caps.maxShaderStorageBlocks[ShaderType::Geometry];
218     mResources.MaxGeometryShaderInvocations   = caps.maxGeometryShaderInvocations;
219     mResources.MaxGeometryImageUniforms       = caps.maxShaderImageUniforms[ShaderType::Geometry];
220 
221     // Subpixel bits.
222     mResources.SubPixelBits = static_cast<int>(caps.subPixelBits);
223 }
224 
225 Compiler::~Compiler() = default;
226 
onDestroy(const Context * context)227 void Compiler::onDestroy(const Context *context)
228 {
229     std::lock_guard<std::mutex> lock(context->getDisplay()->getDisplayGlobalMutex());
230     for (auto &pool : mPools)
231     {
232         for (ShCompilerInstance &instance : pool)
233         {
234             instance.destroy();
235         }
236     }
237     --gActiveCompilers;
238     if (gActiveCompilers == 0)
239     {
240         sh::Finalize();
241     }
242 }
243 
getInstance(ShaderType type)244 ShCompilerInstance Compiler::getInstance(ShaderType type)
245 {
246     ASSERT(type != ShaderType::InvalidEnum);
247     auto &pool = mPools[type];
248     if (pool.empty())
249     {
250         ShHandle handle = sh::ConstructCompiler(ToGLenum(type), mSpec, mOutputType, &mResources);
251         ASSERT(handle);
252         return ShCompilerInstance(handle, mOutputType, type);
253     }
254     else
255     {
256         ShCompilerInstance instance = std::move(pool.back());
257         pool.pop_back();
258         return instance;
259     }
260 }
261 
putInstance(ShCompilerInstance && instance)262 void Compiler::putInstance(ShCompilerInstance &&instance)
263 {
264     static constexpr size_t kMaxPoolSize = 32;
265     auto &pool                           = mPools[instance.getShaderType()];
266     if (pool.size() < kMaxPoolSize)
267     {
268         pool.push_back(std::move(instance));
269     }
270     else
271     {
272         instance.destroy();
273     }
274 }
275 
ShCompilerInstance()276 ShCompilerInstance::ShCompilerInstance() : mHandle(nullptr) {}
277 
ShCompilerInstance(ShHandle handle,ShShaderOutput outputType,ShaderType shaderType)278 ShCompilerInstance::ShCompilerInstance(ShHandle handle,
279                                        ShShaderOutput outputType,
280                                        ShaderType shaderType)
281     : mHandle(handle), mOutputType(outputType), mShaderType(shaderType)
282 {}
283 
~ShCompilerInstance()284 ShCompilerInstance::~ShCompilerInstance()
285 {
286     ASSERT(mHandle == nullptr);
287 }
288 
destroy()289 void ShCompilerInstance::destroy()
290 {
291     if (mHandle != nullptr)
292     {
293         sh::Destruct(mHandle);
294         mHandle = nullptr;
295     }
296 }
297 
ShCompilerInstance(ShCompilerInstance && other)298 ShCompilerInstance::ShCompilerInstance(ShCompilerInstance &&other)
299     : mHandle(other.mHandle), mOutputType(other.mOutputType), mShaderType(other.mShaderType)
300 {
301     other.mHandle = nullptr;
302 }
303 
operator =(ShCompilerInstance && other)304 ShCompilerInstance &ShCompilerInstance::operator=(ShCompilerInstance &&other)
305 {
306     mHandle       = other.mHandle;
307     mOutputType   = other.mOutputType;
308     mShaderType   = other.mShaderType;
309     other.mHandle = nullptr;
310     return *this;
311 }
312 
getHandle()313 ShHandle ShCompilerInstance::getHandle()
314 {
315     return mHandle;
316 }
317 
getShaderType() const318 ShaderType ShCompilerInstance::getShaderType() const
319 {
320     return mShaderType;
321 }
322 
getBuiltinResourcesString()323 const std::string &ShCompilerInstance::getBuiltinResourcesString()
324 {
325     return sh::GetBuiltInResourcesString(mHandle);
326 }
327 
getShaderOutputType() const328 ShShaderOutput ShCompilerInstance::getShaderOutputType() const
329 {
330     return mOutputType;
331 }
332 
333 }  // namespace gl
334