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