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