| // |
| // Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| // |
| |
| // Compiler.cpp: implements the gl::Compiler class. |
| |
| #include "libANGLE/Compiler.h" |
| |
| #include "common/debug.h" |
| #include "libANGLE/ContextState.h" |
| #include "libANGLE/renderer/CompilerImpl.h" |
| #include "libANGLE/renderer/GLImplFactory.h" |
| |
| namespace gl |
| { |
| |
| namespace |
| { |
| |
| // Global count of active shader compiler handles. Needed to know when to call sh::Initialize and |
| // sh::Finalize. |
| size_t activeCompilerHandles = 0; |
| |
| ShShaderSpec SelectShaderSpec(GLint majorVersion, GLint minorVersion, bool isWebGL) |
| { |
| if (majorVersion >= 3) |
| { |
| if (minorVersion == 1) |
| { |
| return isWebGL ? SH_WEBGL3_SPEC : SH_GLES3_1_SPEC; |
| } |
| else |
| { |
| return isWebGL ? SH_WEBGL2_SPEC : SH_GLES3_SPEC; |
| } |
| } |
| return isWebGL ? SH_WEBGL_SPEC : SH_GLES2_SPEC; |
| } |
| |
| } // anonymous namespace |
| |
| Compiler::Compiler(rx::GLImplFactory *implFactory, const ContextState &state) |
| : mImplementation(implFactory->createCompiler()), |
| mSpec(SelectShaderSpec(state.getClientMajorVersion(), |
| state.getClientMinorVersion(), |
| state.getExtensions().webglCompatibility)), |
| mOutputType(mImplementation->getTranslatorOutputType()), |
| mResources(), |
| mFragmentCompiler(nullptr), |
| mVertexCompiler(nullptr), |
| mComputeCompiler(nullptr), |
| mGeometryCompiler(nullptr) |
| { |
| ASSERT(state.getClientMajorVersion() == 2 || state.getClientMajorVersion() == 3); |
| |
| const gl::Caps &caps = state.getCaps(); |
| const gl::Extensions &extensions = state.getExtensions(); |
| |
| sh::InitBuiltInResources(&mResources); |
| mResources.MaxVertexAttribs = caps.maxVertexAttributes; |
| mResources.MaxVertexUniformVectors = caps.maxVertexUniformVectors; |
| mResources.MaxVaryingVectors = caps.maxVaryingVectors; |
| mResources.MaxVertexTextureImageUnits = caps.maxVertexTextureImageUnits; |
| mResources.MaxCombinedTextureImageUnits = caps.maxCombinedTextureImageUnits; |
| mResources.MaxTextureImageUnits = caps.maxTextureImageUnits; |
| mResources.MaxFragmentUniformVectors = caps.maxFragmentUniformVectors; |
| mResources.MaxDrawBuffers = caps.maxDrawBuffers; |
| mResources.OES_standard_derivatives = extensions.standardDerivatives; |
| mResources.EXT_draw_buffers = extensions.drawBuffers; |
| mResources.EXT_shader_texture_lod = extensions.shaderTextureLOD; |
| mResources.OES_EGL_image_external = extensions.eglImageExternal; |
| mResources.OES_EGL_image_external_essl3 = extensions.eglImageExternalEssl3; |
| mResources.NV_EGL_stream_consumer_external = extensions.eglStreamConsumerExternal; |
| mResources.ARB_texture_rectangle = extensions.textureRectangle; |
| // TODO: use shader precision caps to determine if high precision is supported? |
| mResources.FragmentPrecisionHigh = 1; |
| mResources.EXT_frag_depth = extensions.fragDepth; |
| |
| // OVR_multiview state |
| mResources.OVR_multiview = extensions.multiview; |
| mResources.MaxViewsOVR = extensions.maxViews; |
| |
| // GLSL ES 3.0 constants |
| mResources.MaxVertexOutputVectors = caps.maxVertexOutputComponents / 4; |
| mResources.MaxFragmentInputVectors = caps.maxFragmentInputComponents / 4; |
| mResources.MinProgramTexelOffset = caps.minProgramTexelOffset; |
| mResources.MaxProgramTexelOffset = caps.maxProgramTexelOffset; |
| |
| // GLSL ES 3.1 constants |
| mResources.MaxProgramTextureGatherOffset = caps.maxProgramTextureGatherOffset; |
| mResources.MinProgramTextureGatherOffset = caps.minProgramTextureGatherOffset; |
| mResources.MaxImageUnits = caps.maxImageUnits; |
| mResources.MaxVertexImageUniforms = caps.maxVertexImageUniforms; |
| mResources.MaxFragmentImageUniforms = caps.maxFragmentImageUniforms; |
| mResources.MaxComputeImageUniforms = caps.maxComputeImageUniforms; |
| mResources.MaxCombinedImageUniforms = caps.maxCombinedImageUniforms; |
| mResources.MaxCombinedShaderOutputResources = caps.maxCombinedShaderOutputResources; |
| mResources.MaxUniformLocations = caps.maxUniformLocations; |
| |
| for (size_t index = 0u; index < 3u; ++index) |
| { |
| mResources.MaxComputeWorkGroupCount[index] = caps.maxComputeWorkGroupCount[index]; |
| mResources.MaxComputeWorkGroupSize[index] = caps.maxComputeWorkGroupSize[index]; |
| } |
| |
| mResources.MaxComputeUniformComponents = caps.maxComputeUniformComponents; |
| mResources.MaxComputeTextureImageUnits = caps.maxComputeTextureImageUnits; |
| |
| mResources.MaxComputeAtomicCounters = caps.maxComputeAtomicCounters; |
| mResources.MaxComputeAtomicCounterBuffers = caps.maxComputeAtomicCounterBuffers; |
| |
| mResources.MaxVertexAtomicCounters = caps.maxVertexAtomicCounters; |
| mResources.MaxFragmentAtomicCounters = caps.maxFragmentAtomicCounters; |
| mResources.MaxCombinedAtomicCounters = caps.maxCombinedAtomicCounters; |
| mResources.MaxAtomicCounterBindings = caps.maxAtomicCounterBufferBindings; |
| mResources.MaxVertexAtomicCounterBuffers = caps.maxVertexAtomicCounterBuffers; |
| mResources.MaxFragmentAtomicCounterBuffers = caps.maxFragmentAtomicCounterBuffers; |
| mResources.MaxCombinedAtomicCounterBuffers = caps.maxCombinedAtomicCounterBuffers; |
| mResources.MaxAtomicCounterBufferSize = caps.maxAtomicCounterBufferSize; |
| |
| mResources.MaxUniformBufferBindings = caps.maxUniformBufferBindings; |
| mResources.MaxShaderStorageBufferBindings = caps.maxShaderStorageBufferBindings; |
| |
| // Needed by point size clamping workaround |
| mResources.MaxPointSize = caps.maxAliasedPointSize; |
| |
| if (state.getClientMajorVersion() == 2 && !extensions.drawBuffers) |
| { |
| mResources.MaxDrawBuffers = 1; |
| } |
| |
| // Geometry Shader constants |
| mResources.OES_geometry_shader = extensions.geometryShader; |
| // TODO(jiawei.shao@intel.com): initialize all implementation dependent geometry shader limits. |
| mResources.MaxGeometryOutputVertices = extensions.maxGeometryOutputVertices; |
| mResources.MaxGeometryShaderInvocations = extensions.maxGeometryShaderInvocations; |
| } |
| |
| Compiler::~Compiler() |
| { |
| if (mFragmentCompiler) |
| { |
| sh::Destruct(mFragmentCompiler); |
| mFragmentCompiler = nullptr; |
| |
| ASSERT(activeCompilerHandles > 0); |
| activeCompilerHandles--; |
| } |
| |
| if (mVertexCompiler) |
| { |
| sh::Destruct(mVertexCompiler); |
| mVertexCompiler = nullptr; |
| |
| ASSERT(activeCompilerHandles > 0); |
| activeCompilerHandles--; |
| } |
| |
| if (mComputeCompiler) |
| { |
| sh::Destruct(mComputeCompiler); |
| mComputeCompiler = nullptr; |
| |
| ASSERT(activeCompilerHandles > 0); |
| activeCompilerHandles--; |
| } |
| |
| if (activeCompilerHandles == 0) |
| { |
| sh::Finalize(); |
| } |
| |
| ANGLE_SWALLOW_ERR(mImplementation->release()); |
| } |
| |
| ShHandle Compiler::getCompilerHandle(GLenum type) |
| { |
| ShHandle *compiler = nullptr; |
| switch (type) |
| { |
| case GL_VERTEX_SHADER: |
| compiler = &mVertexCompiler; |
| break; |
| |
| case GL_FRAGMENT_SHADER: |
| compiler = &mFragmentCompiler; |
| break; |
| case GL_COMPUTE_SHADER: |
| compiler = &mComputeCompiler; |
| break; |
| case GL_GEOMETRY_SHADER_EXT: |
| compiler = &mGeometryCompiler; |
| break; |
| default: |
| UNREACHABLE(); |
| return nullptr; |
| } |
| |
| if (!(*compiler)) |
| { |
| if (activeCompilerHandles == 0) |
| { |
| sh::Initialize(); |
| } |
| |
| *compiler = sh::ConstructCompiler(type, mSpec, mOutputType, &mResources); |
| ASSERT(*compiler); |
| activeCompilerHandles++; |
| } |
| |
| return *compiler; |
| } |
| |
| const std::string &Compiler::getBuiltinResourcesString(GLenum type) |
| { |
| return sh::GetBuiltInResourcesString(getCompilerHandle(type)); |
| } |
| |
| } // namespace gl |