// // Copyright (c) 2002-2013 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. // // // Implement the top-level of interface to the compiler, // as defined in ShaderLang.h // #include "GLSLANG/ShaderLang.h" #include "compiler/translator/Compiler.h" #include "compiler/translator/InitializeDll.h" #include "compiler/translator/length_limits.h" #ifdef ANGLE_ENABLE_HLSL #include "compiler/translator/TranslatorHLSL.h" #endif // ANGLE_ENABLE_HLSL #include "compiler/translator/VariablePacker.h" #include "angle_gl.h" using namespace sh; namespace { bool isInitialized = false; // // This is the platform independent interface between an OGL driver // and the shading language compiler. // template const std::vector *GetVariableList(const TCompiler *compiler); template <> const std::vector *GetVariableList(const TCompiler *compiler) { return &compiler->getUniforms(); } template <> const std::vector *GetVariableList(const TCompiler *compiler) { return &compiler->getVaryings(); } template <> const std::vector *GetVariableList(const TCompiler *compiler) { return &compiler->getAttributes(); } template <> const std::vector *GetVariableList(const TCompiler *compiler) { return &compiler->getOutputVariables(); } template <> const std::vector *GetVariableList(const TCompiler *compiler) { return &compiler->getInterfaceBlocks(); } template const std::vector *GetShaderVariables(const ShHandle handle) { if (!handle) { return NULL; } TShHandleBase* base = static_cast(handle); TCompiler* compiler = base->getAsCompiler(); if (!compiler) { return NULL; } return GetVariableList(compiler); } TCompiler *GetCompilerFromHandle(ShHandle handle) { if (!handle) return NULL; TShHandleBase *base = static_cast(handle); return base->getAsCompiler(); } #ifdef ANGLE_ENABLE_HLSL TranslatorHLSL *GetTranslatorHLSLFromHandle(ShHandle handle) { if (!handle) return NULL; TShHandleBase *base = static_cast(handle); return base->getAsTranslatorHLSL(); } #endif // ANGLE_ENABLE_HLSL } // anonymous namespace // // Driver must call this first, once, before doing any other compiler operations. // Subsequent calls to this function are no-op. // bool ShInitialize() { if (!isInitialized) { isInitialized = InitProcess(); } return isInitialized; } // // Cleanup symbol tables // bool ShFinalize() { if (isInitialized) { DetachProcess(); isInitialized = false; } return true; } // // Initialize built-in resources with minimum expected values. // void ShInitBuiltInResources(ShBuiltInResources* resources) { // Make comparable. memset(resources, 0, sizeof(*resources)); // Constants. resources->MaxVertexAttribs = 8; resources->MaxVertexUniformVectors = 128; resources->MaxVaryingVectors = 8; resources->MaxVertexTextureImageUnits = 0; resources->MaxCombinedTextureImageUnits = 8; resources->MaxTextureImageUnits = 8; resources->MaxFragmentUniformVectors = 16; resources->MaxDrawBuffers = 1; // Extensions. resources->OES_standard_derivatives = 0; resources->OES_EGL_image_external = 0; resources->OES_EGL_image_external_essl3 = 0; resources->NV_EGL_stream_consumer_external = 0; resources->ARB_texture_rectangle = 0; resources->EXT_blend_func_extended = 0; resources->EXT_draw_buffers = 0; resources->EXT_frag_depth = 0; resources->EXT_shader_texture_lod = 0; resources->WEBGL_debug_shader_precision = 0; resources->EXT_shader_framebuffer_fetch = 0; resources->NV_shader_framebuffer_fetch = 0; resources->ARM_shader_framebuffer_fetch = 0; resources->NV_draw_buffers = 0; // Disable highp precision in fragment shader by default. resources->FragmentPrecisionHigh = 0; // GLSL ES 3.0 constants. resources->MaxVertexOutputVectors = 16; resources->MaxFragmentInputVectors = 15; resources->MinProgramTexelOffset = -8; resources->MaxProgramTexelOffset = 7; // Extensions constants. resources->MaxDualSourceDrawBuffers = 0; // Disable name hashing by default. resources->HashFunction = NULL; resources->ArrayIndexClampingStrategy = SH_CLAMP_WITH_CLAMP_INTRINSIC; resources->MaxExpressionComplexity = 256; resources->MaxCallStackDepth = 256; resources->MaxFunctionParameters = 1024; // ES 3.1 Revision 4, 7.2 Built-in Constants resources->MaxImageUnits = 4; resources->MaxVertexImageUniforms = 0; resources->MaxFragmentImageUniforms = 0; resources->MaxComputeImageUniforms = 4; resources->MaxCombinedImageUniforms = 4; resources->MaxCombinedShaderOutputResources = 4; resources->MaxComputeWorkGroupCount[0] = 65535; resources->MaxComputeWorkGroupCount[1] = 65535; resources->MaxComputeWorkGroupCount[2] = 65535; resources->MaxComputeWorkGroupSize[0] = 128; resources->MaxComputeWorkGroupSize[1] = 128; resources->MaxComputeWorkGroupSize[2] = 64; resources->MaxComputeUniformComponents = 512; resources->MaxComputeTextureImageUnits = 16; resources->MaxComputeAtomicCounters = 8; resources->MaxComputeAtomicCounterBuffers = 1; resources->MaxVertexAtomicCounters = 0; resources->MaxFragmentAtomicCounters = 0; resources->MaxCombinedAtomicCounters = 8; resources->MaxAtomicCounterBindings = 1; resources->MaxVertexAtomicCounterBuffers = 0; resources->MaxFragmentAtomicCounterBuffers = 0; resources->MaxCombinedAtomicCounterBuffers = 1; resources->MaxAtomicCounterBufferSize = 32; } // // Driver calls these to create and destroy compiler objects. // ShHandle ShConstructCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output, const ShBuiltInResources* resources) { TShHandleBase* base = static_cast(ConstructCompiler(type, spec, output)); if (base == nullptr) { return 0; } TCompiler* compiler = base->getAsCompiler(); if (compiler == nullptr) { return 0; } // Generate built-in symbol table. if (!compiler->Init(*resources)) { sh::Destruct(base); return 0; } return reinterpret_cast(base); } void ShDestruct(ShHandle handle) { if (handle == 0) return; TShHandleBase* base = static_cast(handle); if (base->getAsCompiler()) DeleteCompiler(base->getAsCompiler()); } const std::string &ShGetBuiltInResourcesString(const ShHandle handle) { TCompiler *compiler = GetCompilerFromHandle(handle); ASSERT(compiler); return compiler->getBuiltInResourcesString(); } // // Do an actual compile on the given strings. The result is left // in the given compile object. // // Return: The return value of ShCompile is really boolean, indicating // success or failure. // bool ShCompile(const ShHandle handle, const char *const shaderStrings[], size_t numStrings, ShCompileOptions compileOptions) { TCompiler *compiler = GetCompilerFromHandle(handle); ASSERT(compiler); return compiler->compile(shaderStrings, numStrings, compileOptions); } void ShClearResults(const ShHandle handle) { TCompiler *compiler = GetCompilerFromHandle(handle); ASSERT(compiler); compiler->clearResults(); } int ShGetShaderVersion(const ShHandle handle) { TCompiler* compiler = GetCompilerFromHandle(handle); ASSERT(compiler); return compiler->getShaderVersion(); } ShShaderOutput ShGetShaderOutputType(const ShHandle handle) { TCompiler* compiler = GetCompilerFromHandle(handle); ASSERT(compiler); return compiler->getOutputType(); } // // Return any compiler log of messages for the application. // const std::string &ShGetInfoLog(const ShHandle handle) { TCompiler *compiler = GetCompilerFromHandle(handle); ASSERT(compiler); TInfoSink &infoSink = compiler->getInfoSink(); return infoSink.info.str(); } // // Return any object code. // const std::string &ShGetObjectCode(const ShHandle handle) { TCompiler *compiler = GetCompilerFromHandle(handle); ASSERT(compiler); TInfoSink &infoSink = compiler->getInfoSink(); return infoSink.obj.str(); } const std::map *ShGetNameHashingMap( const ShHandle handle) { TCompiler *compiler = GetCompilerFromHandle(handle); ASSERT(compiler); return &(compiler->getNameMap()); } const std::vector *ShGetUniforms(const ShHandle handle) { return GetShaderVariables(handle); } const std::vector *ShGetVaryings(const ShHandle handle) { return GetShaderVariables(handle); } const std::vector *ShGetAttributes(const ShHandle handle) { return GetShaderVariables(handle); } const std::vector *ShGetOutputVariables(const ShHandle handle) { return GetShaderVariables(handle); } const std::vector *ShGetInterfaceBlocks(const ShHandle handle) { return GetShaderVariables(handle); } WorkGroupSize ShGetComputeShaderLocalGroupSize(const ShHandle handle) { ASSERT(handle); TShHandleBase *base = static_cast(handle); TCompiler *compiler = base->getAsCompiler(); ASSERT(compiler); return compiler->getComputeShaderLocalSize(); } bool ShCheckVariablesWithinPackingLimits(int maxVectors, const std::vector &variables) { VariablePacker packer; return packer.CheckVariablesWithinPackingLimits(maxVectors, variables); } bool ShGetInterfaceBlockRegister(const ShHandle handle, const std::string &interfaceBlockName, unsigned int *indexOut) { #ifdef ANGLE_ENABLE_HLSL ASSERT(indexOut); TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle); ASSERT(translator); if (!translator->hasInterfaceBlock(interfaceBlockName)) { return false; } *indexOut = translator->getInterfaceBlockRegister(interfaceBlockName); return true; #else return false; #endif // ANGLE_ENABLE_HLSL } const std::map *ShGetUniformRegisterMap(const ShHandle handle) { #ifdef ANGLE_ENABLE_HLSL TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle); ASSERT(translator); return translator->getUniformRegisterMap(); #else return nullptr; #endif // ANGLE_ENABLE_HLSL } namespace sh { bool Initialize() { return ShInitialize(); } bool Finalize() { return ShFinalize(); } void InitBuiltInResources(ShBuiltInResources *resources) { ShInitBuiltInResources(resources); } const std::string &GetBuiltInResourcesString(const ShHandle handle) { return ShGetBuiltInResourcesString(handle); } ShHandle ConstructCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output, const ShBuiltInResources *resources) { return ShConstructCompiler(type, spec, output, resources); } void Destruct(ShHandle handle) { return ShDestruct(handle); } bool Compile(const ShHandle handle, const char *const shaderStrings[], size_t numStrings, ShCompileOptions compileOptions) { return ShCompile(handle, shaderStrings, numStrings, compileOptions); } void ClearResults(const ShHandle handle) { return ShClearResults(handle); } int GetShaderVersion(const ShHandle handle) { return ShGetShaderVersion(handle); } ShShaderOutput GetShaderOutputType(const ShHandle handle) { return ShGetShaderOutputType(handle); } const std::string &GetInfoLog(const ShHandle handle) { return ShGetInfoLog(handle); } const std::string &GetObjectCode(const ShHandle handle) { return ShGetObjectCode(handle); } const std::map *GetNameHashingMap(const ShHandle handle) { return ShGetNameHashingMap(handle); } const std::vector *GetUniforms(const ShHandle handle) { return ShGetUniforms(handle); } const std::vector *GetVaryings(const ShHandle handle) { return ShGetVaryings(handle); } const std::vector *GetAttributes(const ShHandle handle) { return ShGetAttributes(handle); } const std::vector *GetOutputVariables(const ShHandle handle) { return ShGetOutputVariables(handle); } const std::vector *GetInterfaceBlocks(const ShHandle handle) { return ShGetInterfaceBlocks(handle); } sh::WorkGroupSize GetComputeShaderLocalGroupSize(const ShHandle handle) { return ShGetComputeShaderLocalGroupSize(handle); } bool CheckVariablesWithinPackingLimits(int maxVectors, const std::vector &variables) { return ShCheckVariablesWithinPackingLimits(maxVectors, variables); } bool GetInterfaceBlockRegister(const ShHandle handle, const std::string &interfaceBlockName, unsigned int *indexOut) { return ShGetInterfaceBlockRegister(handle, interfaceBlockName, indexOut); } const std::map *GetUniformRegisterMap(const ShHandle handle) { return ShGetUniformRegisterMap(handle); } } // namespace sh