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 switch (minorVersion)
41 {
42 case 2:
43 ASSERT(!isWebGL);
44 return SH_GLES3_2_SPEC;
45 case 1:
46 return isWebGL ? SH_WEBGL3_SPEC : SH_GLES3_1_SPEC;
47 case 0:
48 return isWebGL ? SH_WEBGL2_SPEC : SH_GLES3_SPEC;
49 default:
50 UNREACHABLE();
51 }
52 }
53
54 // GLES1 emulation: Use GLES3 shader spec.
55 if (!isWebGL && majorVersion == 1)
56 {
57 return SH_GLES3_SPEC;
58 }
59
60 return isWebGL ? SH_WEBGL_SPEC : SH_GLES2_SPEC;
61 }
62
63 } // anonymous namespace
64
Compiler(rx::GLImplFactory * implFactory,const State & state,egl::Display * display)65 Compiler::Compiler(rx::GLImplFactory *implFactory, const State &state, egl::Display *display)
66 : mImplementation(implFactory->createCompiler()),
67 mSpec(SelectShaderSpec(state.getClientMajorVersion(),
68 state.getClientMinorVersion(),
69 state.isWebGL(),
70 state.getClientType())),
71 mOutputType(mImplementation->getTranslatorOutputType()),
72 mResources()
73 {
74 // TODO(http://anglebug.com/3819): Update for GL version specific validation
75 ASSERT(state.getClientMajorVersion() == 1 || state.getClientMajorVersion() == 2 ||
76 state.getClientMajorVersion() == 3 || state.getClientMajorVersion() == 4);
77
78 const gl::Caps &caps = state.getCaps();
79 const gl::Extensions &extensions = state.getExtensions();
80
81 {
82 std::lock_guard<std::mutex> lock(display->getDisplayGlobalMutex());
83 if (gActiveCompilers == 0)
84 {
85 sh::Initialize();
86 }
87 ++gActiveCompilers;
88 }
89
90 sh::InitBuiltInResources(&mResources);
91 mResources.MaxVertexAttribs = caps.maxVertexAttributes;
92 mResources.MaxVertexUniformVectors = caps.maxVertexUniformVectors;
93 mResources.MaxVaryingVectors = caps.maxVaryingVectors;
94 mResources.MaxVertexTextureImageUnits = caps.maxShaderTextureImageUnits[ShaderType::Vertex];
95 mResources.MaxCombinedTextureImageUnits = caps.maxCombinedTextureImageUnits;
96 mResources.MaxTextureImageUnits = caps.maxShaderTextureImageUnits[ShaderType::Fragment];
97 mResources.MaxFragmentUniformVectors = caps.maxFragmentUniformVectors;
98 mResources.MaxDrawBuffers = caps.maxDrawBuffers;
99 mResources.OES_standard_derivatives = extensions.standardDerivativesOES;
100 mResources.EXT_draw_buffers = extensions.drawBuffersEXT;
101 mResources.EXT_shader_texture_lod = extensions.shaderTextureLodEXT;
102 mResources.EXT_shader_non_constant_global_initializers =
103 extensions.shaderNonConstantGlobalInitializersEXT;
104 mResources.OES_EGL_image_external = extensions.EGLImageExternalOES;
105 mResources.OES_EGL_image_external_essl3 = extensions.EGLImageExternalEssl3OES;
106 mResources.NV_EGL_stream_consumer_external = extensions.EGLStreamConsumerExternalNV;
107 mResources.NV_shader_noperspective_interpolation =
108 extensions.shaderNoperspectiveInterpolationNV;
109 mResources.ARB_texture_rectangle = extensions.textureRectangleANGLE;
110 mResources.EXT_gpu_shader5 = extensions.gpuShader5EXT;
111 mResources.OES_shader_io_blocks = extensions.shaderIoBlocksOES;
112 mResources.EXT_shader_io_blocks = extensions.shaderIoBlocksEXT;
113 mResources.OES_texture_storage_multisample_2d_array =
114 extensions.textureStorageMultisample2dArrayOES;
115 mResources.OES_texture_3D = extensions.texture3DOES;
116 mResources.ANGLE_texture_multisample = extensions.textureMultisampleANGLE;
117 mResources.ANGLE_multi_draw = extensions.multiDrawANGLE;
118 mResources.ANGLE_base_vertex_base_instance_shader_builtin =
119 extensions.baseVertexBaseInstanceShaderBuiltinANGLE;
120 mResources.APPLE_clip_distance = extensions.clipDistanceAPPLE;
121 // OES_shader_multisample_interpolation
122 mResources.OES_shader_multisample_interpolation = extensions.shaderMultisampleInterpolationOES;
123 mResources.OES_shader_image_atomic = extensions.shaderImageAtomicOES;
124 // TODO: use shader precision caps to determine if high precision is supported?
125 mResources.FragmentPrecisionHigh = 1;
126 mResources.EXT_frag_depth = extensions.fragDepthEXT;
127
128 // OVR_multiview state
129 mResources.OVR_multiview = extensions.multiviewOVR;
130
131 // OVR_multiview2 state
132 mResources.OVR_multiview2 = extensions.multiview2OVR;
133 mResources.MaxViewsOVR = caps.maxViews;
134
135 // EXT_multisampled_render_to_texture and EXT_multisampled_render_to_texture2
136 mResources.EXT_multisampled_render_to_texture = extensions.multisampledRenderToTextureEXT;
137 mResources.EXT_multisampled_render_to_texture2 = extensions.multisampledRenderToTexture2EXT;
138
139 // WEBGL_video_texture
140 mResources.WEBGL_video_texture = extensions.videoTextureWEBGL;
141
142 // OES_texture_cube_map_array
143 mResources.OES_texture_cube_map_array = extensions.textureCubeMapArrayOES;
144 mResources.EXT_texture_cube_map_array = extensions.textureCubeMapArrayEXT;
145
146 // EXT_shadow_samplers
147 mResources.EXT_shadow_samplers = extensions.shadowSamplersEXT;
148
149 // OES_texture_buffer
150 mResources.OES_texture_buffer = extensions.textureBufferOES;
151 mResources.EXT_texture_buffer = extensions.textureBufferEXT;
152
153 // GL_EXT_YUV_target
154 mResources.EXT_YUV_target = extensions.YUVTargetEXT;
155
156 mResources.EXT_shader_framebuffer_fetch_non_coherent =
157 extensions.shaderFramebufferFetchNonCoherentEXT;
158
159 mResources.EXT_shader_framebuffer_fetch = extensions.shaderFramebufferFetchEXT;
160
161 // GL_EXT_clip_cull_distance
162 mResources.EXT_clip_cull_distance = extensions.clipCullDistanceEXT;
163
164 // GL_EXT_primitive_bounding_box
165 mResources.EXT_primitive_bounding_box = extensions.primitiveBoundingBoxEXT;
166
167 // GL_OES_primitive_bounding_box
168 mResources.OES_primitive_bounding_box = extensions.primitiveBoundingBoxOES;
169
170 // GLSL ES 3.0 constants
171 mResources.MaxVertexOutputVectors = caps.maxVertexOutputComponents / 4;
172 mResources.MaxFragmentInputVectors = caps.maxFragmentInputComponents / 4;
173 mResources.MinProgramTexelOffset = caps.minProgramTexelOffset;
174 mResources.MaxProgramTexelOffset = caps.maxProgramTexelOffset;
175
176 // EXT_blend_func_extended
177 mResources.EXT_blend_func_extended = extensions.blendFuncExtendedEXT;
178 mResources.MaxDualSourceDrawBuffers = caps.maxDualSourceDrawBuffers;
179
180 // APPLE_clip_distance/EXT_clip_cull_distance
181 mResources.MaxClipDistances = caps.maxClipDistances;
182 mResources.MaxCullDistances = caps.maxCullDistances;
183 mResources.MaxCombinedClipAndCullDistances = caps.maxCombinedClipAndCullDistances;
184
185 // OES_sample_variables
186 mResources.OES_sample_variables = extensions.sampleVariablesOES;
187 mResources.MaxSamples = caps.maxSamples;
188
189 // ANDROID_extension_pack_es31a
190 mResources.ANDROID_extension_pack_es31a = extensions.extensionPackEs31aANDROID;
191
192 // KHR_blend_equation_advanced
193 mResources.KHR_blend_equation_advanced = extensions.blendEquationAdvancedKHR;
194
195 // GLSL ES 3.1 constants
196 mResources.MaxProgramTextureGatherOffset = caps.maxProgramTextureGatherOffset;
197 mResources.MinProgramTextureGatherOffset = caps.minProgramTextureGatherOffset;
198 mResources.MaxImageUnits = caps.maxImageUnits;
199 mResources.MaxVertexImageUniforms = caps.maxShaderImageUniforms[ShaderType::Vertex];
200 mResources.MaxFragmentImageUniforms = caps.maxShaderImageUniforms[ShaderType::Fragment];
201 mResources.MaxComputeImageUniforms = caps.maxShaderImageUniforms[ShaderType::Compute];
202 mResources.MaxCombinedImageUniforms = caps.maxCombinedImageUniforms;
203 mResources.MaxCombinedShaderOutputResources = caps.maxCombinedShaderOutputResources;
204 mResources.MaxUniformLocations = caps.maxUniformLocations;
205
206 for (size_t index = 0u; index < 3u; ++index)
207 {
208 mResources.MaxComputeWorkGroupCount[index] = caps.maxComputeWorkGroupCount[index];
209 mResources.MaxComputeWorkGroupSize[index] = caps.maxComputeWorkGroupSize[index];
210 }
211
212 mResources.MaxComputeUniformComponents = caps.maxShaderUniformComponents[ShaderType::Compute];
213 mResources.MaxComputeTextureImageUnits = caps.maxShaderTextureImageUnits[ShaderType::Compute];
214
215 mResources.MaxComputeAtomicCounters = caps.maxShaderAtomicCounters[ShaderType::Compute];
216 mResources.MaxComputeAtomicCounterBuffers =
217 caps.maxShaderAtomicCounterBuffers[ShaderType::Compute];
218
219 mResources.MaxVertexAtomicCounters = caps.maxShaderAtomicCounters[ShaderType::Vertex];
220 mResources.MaxFragmentAtomicCounters = caps.maxShaderAtomicCounters[ShaderType::Fragment];
221 mResources.MaxCombinedAtomicCounters = caps.maxCombinedAtomicCounters;
222 mResources.MaxAtomicCounterBindings = caps.maxAtomicCounterBufferBindings;
223 mResources.MaxVertexAtomicCounterBuffers =
224 caps.maxShaderAtomicCounterBuffers[ShaderType::Vertex];
225 mResources.MaxFragmentAtomicCounterBuffers =
226 caps.maxShaderAtomicCounterBuffers[ShaderType::Fragment];
227 mResources.MaxCombinedAtomicCounterBuffers = caps.maxCombinedAtomicCounterBuffers;
228 mResources.MaxAtomicCounterBufferSize = caps.maxAtomicCounterBufferSize;
229
230 mResources.MaxUniformBufferBindings = caps.maxUniformBufferBindings;
231 mResources.MaxShaderStorageBufferBindings = caps.maxShaderStorageBufferBindings;
232
233 // Needed by point size clamping workaround
234 mResources.MaxPointSize = caps.maxAliasedPointSize;
235
236 if (state.getClientMajorVersion() == 2 && !extensions.drawBuffersEXT)
237 {
238 mResources.MaxDrawBuffers = 1;
239 }
240
241 // Geometry Shader constants
242 mResources.EXT_geometry_shader = extensions.geometryShaderEXT;
243 mResources.OES_geometry_shader = extensions.geometryShaderOES;
244 mResources.MaxGeometryUniformComponents = caps.maxShaderUniformComponents[ShaderType::Geometry];
245 mResources.MaxGeometryUniformBlocks = caps.maxShaderUniformBlocks[ShaderType::Geometry];
246 mResources.MaxGeometryInputComponents = caps.maxGeometryInputComponents;
247 mResources.MaxGeometryOutputComponents = caps.maxGeometryOutputComponents;
248 mResources.MaxGeometryOutputVertices = caps.maxGeometryOutputVertices;
249 mResources.MaxGeometryTotalOutputComponents = caps.maxGeometryTotalOutputComponents;
250 mResources.MaxGeometryTextureImageUnits = caps.maxShaderTextureImageUnits[ShaderType::Geometry];
251
252 mResources.MaxGeometryAtomicCounterBuffers =
253 caps.maxShaderAtomicCounterBuffers[ShaderType::Geometry];
254 mResources.MaxGeometryAtomicCounters = caps.maxShaderAtomicCounters[ShaderType::Geometry];
255 mResources.MaxGeometryShaderStorageBlocks = caps.maxShaderStorageBlocks[ShaderType::Geometry];
256 mResources.MaxGeometryShaderInvocations = caps.maxGeometryShaderInvocations;
257 mResources.MaxGeometryImageUniforms = caps.maxShaderImageUniforms[ShaderType::Geometry];
258
259 // Tessellation Shader constants
260 mResources.EXT_tessellation_shader = extensions.tessellationShaderEXT;
261 mResources.MaxTessControlInputComponents = caps.maxTessControlInputComponents;
262 mResources.MaxTessControlOutputComponents = caps.maxTessControlOutputComponents;
263 mResources.MaxTessControlTextureImageUnits =
264 caps.maxShaderTextureImageUnits[ShaderType::TessControl];
265 mResources.MaxTessControlUniformComponents =
266 caps.maxShaderUniformComponents[ShaderType::TessControl];
267 mResources.MaxTessControlTotalOutputComponents = caps.maxTessControlTotalOutputComponents;
268 mResources.MaxTessControlImageUniforms = caps.maxShaderImageUniforms[ShaderType::TessControl];
269 mResources.MaxTessControlAtomicCounters = caps.maxShaderAtomicCounters[ShaderType::TessControl];
270 mResources.MaxTessControlAtomicCounterBuffers =
271 caps.maxShaderAtomicCounterBuffers[ShaderType::TessControl];
272
273 mResources.MaxTessPatchComponents = caps.maxTessPatchComponents;
274 mResources.MaxPatchVertices = caps.maxPatchVertices;
275 mResources.MaxTessGenLevel = caps.maxTessGenLevel;
276
277 mResources.MaxTessEvaluationInputComponents = caps.maxTessEvaluationInputComponents;
278 mResources.MaxTessEvaluationOutputComponents = caps.maxTessEvaluationOutputComponents;
279 mResources.MaxTessEvaluationTextureImageUnits =
280 caps.maxShaderTextureImageUnits[ShaderType::TessEvaluation];
281 mResources.MaxTessEvaluationUniformComponents =
282 caps.maxShaderUniformComponents[ShaderType::TessEvaluation];
283 mResources.MaxTessEvaluationImageUniforms =
284 caps.maxShaderImageUniforms[ShaderType::TessEvaluation];
285 mResources.MaxTessEvaluationAtomicCounters =
286 caps.maxShaderAtomicCounters[ShaderType::TessEvaluation];
287 mResources.MaxTessEvaluationAtomicCounterBuffers =
288 caps.maxShaderAtomicCounterBuffers[ShaderType::TessEvaluation];
289
290 // Subpixel bits.
291 mResources.SubPixelBits = static_cast<int>(caps.subPixelBits);
292
293 // Direct-to-metal constants:
294 mResources.DriverUniformsBindingIndex = caps.driverUniformsBindingIndex;
295 mResources.DefaultUniformsBindingIndex = caps.defaultUniformsBindingIndex;
296 mResources.UBOArgumentBufferBindingIndex = caps.UBOArgumentBufferBindingIndex;
297 }
298
299 Compiler::~Compiler() = default;
300
onDestroy(const Context * context)301 void Compiler::onDestroy(const Context *context)
302 {
303 std::lock_guard<std::mutex> lock(context->getDisplay()->getDisplayGlobalMutex());
304 for (auto &pool : mPools)
305 {
306 for (ShCompilerInstance &instance : pool)
307 {
308 instance.destroy();
309 }
310 }
311 --gActiveCompilers;
312 if (gActiveCompilers == 0)
313 {
314 sh::Finalize();
315 }
316 }
317
getInstance(ShaderType type)318 ShCompilerInstance Compiler::getInstance(ShaderType type)
319 {
320 ASSERT(type != ShaderType::InvalidEnum);
321 auto &pool = mPools[type];
322 if (pool.empty())
323 {
324 ShHandle handle = sh::ConstructCompiler(ToGLenum(type), mSpec, mOutputType, &mResources);
325 ASSERT(handle);
326 return ShCompilerInstance(handle, mOutputType, type);
327 }
328 else
329 {
330 ShCompilerInstance instance = std::move(pool.back());
331 pool.pop_back();
332 return instance;
333 }
334 }
335
putInstance(ShCompilerInstance && instance)336 void Compiler::putInstance(ShCompilerInstance &&instance)
337 {
338 static constexpr size_t kMaxPoolSize = 32;
339 auto &pool = mPools[instance.getShaderType()];
340 if (pool.size() < kMaxPoolSize)
341 {
342 pool.push_back(std::move(instance));
343 }
344 else
345 {
346 instance.destroy();
347 }
348 }
349
ShCompilerInstance()350 ShCompilerInstance::ShCompilerInstance() : mHandle(nullptr) {}
351
ShCompilerInstance(ShHandle handle,ShShaderOutput outputType,ShaderType shaderType)352 ShCompilerInstance::ShCompilerInstance(ShHandle handle,
353 ShShaderOutput outputType,
354 ShaderType shaderType)
355 : mHandle(handle), mOutputType(outputType), mShaderType(shaderType)
356 {}
357
~ShCompilerInstance()358 ShCompilerInstance::~ShCompilerInstance()
359 {
360 ASSERT(mHandle == nullptr);
361 }
362
destroy()363 void ShCompilerInstance::destroy()
364 {
365 if (mHandle != nullptr)
366 {
367 sh::Destruct(mHandle);
368 mHandle = nullptr;
369 }
370 }
371
ShCompilerInstance(ShCompilerInstance && other)372 ShCompilerInstance::ShCompilerInstance(ShCompilerInstance &&other)
373 : mHandle(other.mHandle), mOutputType(other.mOutputType), mShaderType(other.mShaderType)
374 {
375 other.mHandle = nullptr;
376 }
377
operator =(ShCompilerInstance && other)378 ShCompilerInstance &ShCompilerInstance::operator=(ShCompilerInstance &&other)
379 {
380 mHandle = other.mHandle;
381 mOutputType = other.mOutputType;
382 mShaderType = other.mShaderType;
383 other.mHandle = nullptr;
384 return *this;
385 }
386
getHandle()387 ShHandle ShCompilerInstance::getHandle()
388 {
389 return mHandle;
390 }
391
getShaderType() const392 ShaderType ShCompilerInstance::getShaderType() const
393 {
394 return mShaderType;
395 }
396
getBuiltinResourcesString()397 const std::string &ShCompilerInstance::getBuiltinResourcesString()
398 {
399 return sh::GetBuiltInResourcesString(mHandle);
400 }
401
getShaderOutputType() const402 ShShaderOutput ShCompilerInstance::getShaderOutputType() const
403 {
404 return mOutputType;
405 }
406
407 } // namespace gl
408