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
108 // TODO: use shader precision caps to determine if high precision is supported?
109 mResources.FragmentPrecisionHigh = 1;
110 mResources.EXT_frag_depth = extensions.fragDepth;
111
112 // OVR_multiview state
113 mResources.OVR_multiview = extensions.multiview;
114
115 // OVR_multiview2 state
116 mResources.OVR_multiview2 = extensions.multiview2;
117 mResources.MaxViewsOVR = extensions.maxViews;
118
119 // EXT_multisampled_render_to_texture
120 mResources.EXT_multisampled_render_to_texture = extensions.multisampledRenderToTexture;
121
122 // WEBGL_video_texture
123 mResources.WEBGL_video_texture = extensions.webglVideoTexture;
124
125 // GLSL ES 3.0 constants
126 mResources.MaxVertexOutputVectors = caps.maxVertexOutputComponents / 4;
127 mResources.MaxFragmentInputVectors = caps.maxFragmentInputComponents / 4;
128 mResources.MinProgramTexelOffset = caps.minProgramTexelOffset;
129 mResources.MaxProgramTexelOffset = caps.maxProgramTexelOffset;
130
131 // EXT_blend_func_extended
132 mResources.EXT_blend_func_extended = extensions.blendFuncExtended;
133 mResources.MaxDualSourceDrawBuffers = extensions.maxDualSourceDrawBuffers;
134
135 // GLSL ES 3.1 constants
136 mResources.MaxProgramTextureGatherOffset = caps.maxProgramTextureGatherOffset;
137 mResources.MinProgramTextureGatherOffset = caps.minProgramTextureGatherOffset;
138 mResources.MaxImageUnits = caps.maxImageUnits;
139 mResources.MaxVertexImageUniforms = caps.maxShaderImageUniforms[ShaderType::Vertex];
140 mResources.MaxFragmentImageUniforms = caps.maxShaderImageUniforms[ShaderType::Fragment];
141 mResources.MaxComputeImageUniforms = caps.maxShaderImageUniforms[ShaderType::Compute];
142 mResources.MaxCombinedImageUniforms = caps.maxCombinedImageUniforms;
143 mResources.MaxCombinedShaderOutputResources = caps.maxCombinedShaderOutputResources;
144 mResources.MaxUniformLocations = caps.maxUniformLocations;
145
146 for (size_t index = 0u; index < 3u; ++index)
147 {
148 mResources.MaxComputeWorkGroupCount[index] = caps.maxComputeWorkGroupCount[index];
149 mResources.MaxComputeWorkGroupSize[index] = caps.maxComputeWorkGroupSize[index];
150 }
151
152 mResources.MaxComputeUniformComponents = caps.maxShaderUniformComponents[ShaderType::Compute];
153 mResources.MaxComputeTextureImageUnits = caps.maxShaderTextureImageUnits[ShaderType::Compute];
154
155 mResources.MaxComputeAtomicCounters = caps.maxShaderAtomicCounters[ShaderType::Compute];
156 mResources.MaxComputeAtomicCounterBuffers =
157 caps.maxShaderAtomicCounterBuffers[ShaderType::Compute];
158
159 mResources.MaxVertexAtomicCounters = caps.maxShaderAtomicCounters[ShaderType::Vertex];
160 mResources.MaxFragmentAtomicCounters = caps.maxShaderAtomicCounters[ShaderType::Fragment];
161 mResources.MaxCombinedAtomicCounters = caps.maxCombinedAtomicCounters;
162 mResources.MaxAtomicCounterBindings = caps.maxAtomicCounterBufferBindings;
163 mResources.MaxVertexAtomicCounterBuffers =
164 caps.maxShaderAtomicCounterBuffers[ShaderType::Vertex];
165 mResources.MaxFragmentAtomicCounterBuffers =
166 caps.maxShaderAtomicCounterBuffers[ShaderType::Fragment];
167 mResources.MaxCombinedAtomicCounterBuffers = caps.maxCombinedAtomicCounterBuffers;
168 mResources.MaxAtomicCounterBufferSize = caps.maxAtomicCounterBufferSize;
169
170 mResources.MaxUniformBufferBindings = caps.maxUniformBufferBindings;
171 mResources.MaxShaderStorageBufferBindings = caps.maxShaderStorageBufferBindings;
172
173 // Needed by point size clamping workaround
174 mResources.MaxPointSize = caps.maxAliasedPointSize;
175
176 if (state.getClientMajorVersion() == 2 && !extensions.drawBuffers)
177 {
178 mResources.MaxDrawBuffers = 1;
179 }
180
181 // Geometry Shader constants
182 mResources.EXT_geometry_shader = extensions.geometryShader;
183 mResources.MaxGeometryUniformComponents = caps.maxShaderUniformComponents[ShaderType::Geometry];
184 mResources.MaxGeometryUniformBlocks = caps.maxShaderUniformBlocks[ShaderType::Geometry];
185 mResources.MaxGeometryInputComponents = caps.maxGeometryInputComponents;
186 mResources.MaxGeometryOutputComponents = caps.maxGeometryOutputComponents;
187 mResources.MaxGeometryOutputVertices = caps.maxGeometryOutputVertices;
188 mResources.MaxGeometryTotalOutputComponents = caps.maxGeometryTotalOutputComponents;
189 mResources.MaxGeometryTextureImageUnits = caps.maxShaderTextureImageUnits[ShaderType::Geometry];
190
191 mResources.MaxGeometryAtomicCounterBuffers =
192 caps.maxShaderAtomicCounterBuffers[ShaderType::Geometry];
193 mResources.MaxGeometryAtomicCounters = caps.maxShaderAtomicCounters[ShaderType::Geometry];
194 mResources.MaxGeometryShaderStorageBlocks = caps.maxShaderStorageBlocks[ShaderType::Geometry];
195 mResources.MaxGeometryShaderInvocations = caps.maxGeometryShaderInvocations;
196 mResources.MaxGeometryImageUniforms = caps.maxShaderImageUniforms[ShaderType::Geometry];
197
198 // Subpixel bits.
199 mResources.SubPixelBits = static_cast<int>(caps.subPixelBits);
200 }
201
~Compiler()202 Compiler::~Compiler()
203 {
204 for (auto &pool : mPools)
205 {
206 for (ShCompilerInstance &instance : pool)
207 {
208 instance.destroy();
209 }
210 }
211 --gActiveCompilers;
212 if (gActiveCompilers == 0)
213 {
214 sh::Finalize();
215 }
216 }
217
getInstance(ShaderType type)218 ShCompilerInstance Compiler::getInstance(ShaderType type)
219 {
220 ASSERT(type != ShaderType::InvalidEnum);
221 auto &pool = mPools[type];
222 if (pool.empty())
223 {
224 ShHandle handle = sh::ConstructCompiler(ToGLenum(type), mSpec, mOutputType, &mResources);
225 ASSERT(handle);
226 return ShCompilerInstance(handle, mOutputType, type);
227 }
228 else
229 {
230 ShCompilerInstance instance = std::move(pool.back());
231 pool.pop_back();
232 return instance;
233 }
234 }
235
putInstance(ShCompilerInstance && instance)236 void Compiler::putInstance(ShCompilerInstance &&instance)
237 {
238 static constexpr size_t kMaxPoolSize = 32;
239 auto &pool = mPools[instance.getShaderType()];
240 if (pool.size() < kMaxPoolSize)
241 {
242 pool.push_back(std::move(instance));
243 }
244 else
245 {
246 instance.destroy();
247 }
248 }
249
ShCompilerInstance()250 ShCompilerInstance::ShCompilerInstance() : mHandle(nullptr) {}
251
ShCompilerInstance(ShHandle handle,ShShaderOutput outputType,ShaderType shaderType)252 ShCompilerInstance::ShCompilerInstance(ShHandle handle,
253 ShShaderOutput outputType,
254 ShaderType shaderType)
255 : mHandle(handle), mOutputType(outputType), mShaderType(shaderType)
256 {}
257
~ShCompilerInstance()258 ShCompilerInstance::~ShCompilerInstance()
259 {
260 ASSERT(mHandle == nullptr);
261 }
262
destroy()263 void ShCompilerInstance::destroy()
264 {
265 if (mHandle != nullptr)
266 {
267 sh::Destruct(mHandle);
268 mHandle = nullptr;
269 }
270 }
271
ShCompilerInstance(ShCompilerInstance && other)272 ShCompilerInstance::ShCompilerInstance(ShCompilerInstance &&other)
273 : mHandle(other.mHandle), mOutputType(other.mOutputType), mShaderType(other.mShaderType)
274 {
275 other.mHandle = nullptr;
276 }
277
operator =(ShCompilerInstance && other)278 ShCompilerInstance &ShCompilerInstance::operator=(ShCompilerInstance &&other)
279 {
280 mHandle = other.mHandle;
281 mOutputType = other.mOutputType;
282 mShaderType = other.mShaderType;
283 other.mHandle = nullptr;
284 return *this;
285 }
286
getHandle()287 ShHandle ShCompilerInstance::getHandle()
288 {
289 return mHandle;
290 }
291
getShaderType() const292 ShaderType ShCompilerInstance::getShaderType() const
293 {
294 return mShaderType;
295 }
296
getBuiltinResourcesString()297 const std::string &ShCompilerInstance::getBuiltinResourcesString()
298 {
299 return sh::GetBuiltInResourcesString(mHandle);
300 }
301
getShaderOutputType() const302 ShShaderOutput ShCompilerInstance::getShaderOutputType() const
303 {
304 return mOutputType;
305 }
306
307 } // namespace gl
308