// // Copyright 2002 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 "angle_gl.h" #include "compiler/translator/VariablePacker.h" 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->getInterfaceBlocks(); } TCompiler *GetCompilerFromHandle(ShHandle handle) { if (!handle) { return nullptr; } TShHandleBase *base = static_cast(handle); return base->getAsCompiler(); } template const std::vector *GetShaderVariables(const ShHandle handle) { TCompiler *compiler = GetCompilerFromHandle(handle); if (!compiler) { return nullptr; } return GetVariableList(compiler); } #ifdef ANGLE_ENABLE_HLSL TranslatorHLSL *GetTranslatorHLSLFromHandle(ShHandle handle) { if (!handle) return nullptr; TShHandleBase *base = static_cast(handle); return base->getAsTranslatorHLSL(); } #endif // ANGLE_ENABLE_HLSL GLenum GetGeometryShaderPrimitiveTypeEnum(sh::TLayoutPrimitiveType primitiveType) { switch (primitiveType) { case EptPoints: return GL_POINTS; case EptLines: return GL_LINES; case EptLinesAdjacency: return GL_LINES_ADJACENCY_EXT; case EptTriangles: return GL_TRIANGLES; case EptTrianglesAdjacency: return GL_TRIANGLES_ADJACENCY_EXT; case EptLineStrip: return GL_LINE_STRIP; case EptTriangleStrip: return GL_TRIANGLE_STRIP; case EptUndefined: default: UNREACHABLE(); return GL_INVALID_VALUE; } } } // anonymous namespace // // Driver must call this first, once, before doing any other compiler operations. // Subsequent calls to this function are no-op. // bool Initialize() { if (!isInitialized) { isInitialized = InitProcess(); } return isInitialized; } // // Cleanup symbol tables // bool Finalize() { if (isInitialized) { DetachProcess(); isInitialized = false; } return true; } // // Initialize built-in resources with minimum expected values. // void InitBuiltInResources(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->OVR_multiview = 0; resources->OVR_multiview2 = 0; resources->EXT_YUV_target = 0; resources->EXT_geometry_shader = 0; resources->EXT_gpu_shader5 = 0; resources->EXT_shader_non_constant_global_initializers = 0; resources->NV_shader_noperspective_interpolation = 0; resources->OES_texture_storage_multisample_2d_array = 0; resources->OES_texture_3D = 0; resources->ANGLE_texture_multisample = 0; resources->ANGLE_multi_draw = 0; resources->ANGLE_base_vertex_base_instance = 0; resources->WEBGL_video_texture = 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; resources->MaxViewsOVR = 4; // Disable name hashing by default. resources->HashFunction = nullptr; 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 // ES 3.1, Revision 4, 8.13 Texture minification // "The value of MIN_PROGRAM_TEXTURE_GATHER_OFFSET must be less than or equal to the value of // MIN_PROGRAM_TEXEL_OFFSET. The value of MAX_PROGRAM_TEXTURE_GATHER_OFFSET must be greater than // or equal to the value of MAX_PROGRAM_TEXEL_OFFSET" resources->MinProgramTextureGatherOffset = -8; resources->MaxProgramTextureGatherOffset = 7; resources->MaxImageUnits = 4; resources->MaxVertexImageUniforms = 0; resources->MaxFragmentImageUniforms = 0; resources->MaxComputeImageUniforms = 4; resources->MaxCombinedImageUniforms = 4; resources->MaxUniformLocations = 1024; 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; resources->MaxUniformBufferBindings = 32; resources->MaxShaderStorageBufferBindings = 4; resources->MaxGeometryUniformComponents = 1024; resources->MaxGeometryUniformBlocks = 12; resources->MaxGeometryInputComponents = 64; resources->MaxGeometryOutputComponents = 64; resources->MaxGeometryOutputVertices = 256; resources->MaxGeometryTotalOutputComponents = 1024; resources->MaxGeometryTextureImageUnits = 16; resources->MaxGeometryAtomicCounterBuffers = 0; resources->MaxGeometryAtomicCounters = 0; resources->MaxGeometryShaderStorageBlocks = 0; resources->MaxGeometryShaderInvocations = 32; resources->MaxGeometryImageUniforms = 0; resources->SubPixelBits = 8; } // // Driver calls these to create and destroy compiler objects. // ShHandle ConstructCompiler(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)) { Destruct(base); return 0; } return base; } void Destruct(ShHandle handle) { if (handle == 0) return; TShHandleBase *base = static_cast(handle); if (base->getAsCompiler()) DeleteCompiler(base->getAsCompiler()); } const std::string &GetBuiltInResourcesString(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 Compile(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 ClearResults(const ShHandle handle) { TCompiler *compiler = GetCompilerFromHandle(handle); ASSERT(compiler); compiler->clearResults(); } int GetShaderVersion(const ShHandle handle) { TCompiler *compiler = GetCompilerFromHandle(handle); ASSERT(compiler); return compiler->getShaderVersion(); } ShShaderOutput GetShaderOutputType(const ShHandle handle) { TCompiler *compiler = GetCompilerFromHandle(handle); ASSERT(compiler); return compiler->getOutputType(); } // // Return any compiler log of messages for the application. // const std::string &GetInfoLog(const ShHandle handle) { TCompiler *compiler = GetCompilerFromHandle(handle); ASSERT(compiler); TInfoSink &infoSink = compiler->getInfoSink(); return infoSink.info.str(); } // // Return any object code. // const std::string &GetObjectCode(const ShHandle handle) { TCompiler *compiler = GetCompilerFromHandle(handle); ASSERT(compiler); TInfoSink &infoSink = compiler->getInfoSink(); return infoSink.obj.str(); } const std::map *GetNameHashingMap(const ShHandle handle) { TCompiler *compiler = GetCompilerFromHandle(handle); ASSERT(compiler); return &(compiler->getNameMap()); } const std::vector *GetUniforms(const ShHandle handle) { TCompiler *compiler = GetCompilerFromHandle(handle); if (!compiler) { return nullptr; } return &compiler->getUniforms(); } const std::vector *GetInputVaryings(const ShHandle handle) { TCompiler *compiler = GetCompilerFromHandle(handle); if (compiler == nullptr) { return nullptr; } return &compiler->getInputVaryings(); } const std::vector *GetOutputVaryings(const ShHandle handle) { TCompiler *compiler = GetCompilerFromHandle(handle); if (compiler == nullptr) { return nullptr; } return &compiler->getOutputVaryings(); } const std::vector *GetVaryings(const ShHandle handle) { TCompiler *compiler = GetCompilerFromHandle(handle); if (compiler == nullptr) { return nullptr; } switch (compiler->getShaderType()) { case GL_VERTEX_SHADER: return &compiler->getOutputVaryings(); case GL_FRAGMENT_SHADER: return &compiler->getInputVaryings(); case GL_COMPUTE_SHADER: ASSERT(compiler->getOutputVaryings().empty() && compiler->getInputVaryings().empty()); return &compiler->getOutputVaryings(); // Since geometry shaders have both input and output varyings, we shouldn't call GetVaryings // on a geometry shader. default: return nullptr; } } const std::vector *GetAttributes(const ShHandle handle) { TCompiler *compiler = GetCompilerFromHandle(handle); if (!compiler) { return nullptr; } return &compiler->getAttributes(); } const std::vector *GetOutputVariables(const ShHandle handle) { TCompiler *compiler = GetCompilerFromHandle(handle); if (!compiler) { return nullptr; } return &compiler->getOutputVariables(); } const std::vector *GetInterfaceBlocks(const ShHandle handle) { return GetShaderVariables(handle); } const std::vector *GetUniformBlocks(const ShHandle handle) { ASSERT(handle); TShHandleBase *base = static_cast(handle); TCompiler *compiler = base->getAsCompiler(); ASSERT(compiler); return &compiler->getUniformBlocks(); } const std::vector *GetShaderStorageBlocks(const ShHandle handle) { ASSERT(handle); TShHandleBase *base = static_cast(handle); TCompiler *compiler = base->getAsCompiler(); ASSERT(compiler); return &compiler->getShaderStorageBlocks(); } WorkGroupSize GetComputeShaderLocalGroupSize(const ShHandle handle) { ASSERT(handle); TShHandleBase *base = static_cast(handle); TCompiler *compiler = base->getAsCompiler(); ASSERT(compiler); return compiler->getComputeShaderLocalSize(); } int GetVertexShaderNumViews(const ShHandle handle) { ASSERT(handle); TShHandleBase *base = static_cast(handle); TCompiler *compiler = base->getAsCompiler(); ASSERT(compiler); return compiler->getNumViews(); } bool HasEarlyFragmentTestsOptimization(const ShHandle handle) { TCompiler *compiler = GetCompilerFromHandle(handle); if (compiler == nullptr) { return false; } return compiler->isEarlyFragmentTestsOptimized(); } bool CheckVariablesWithinPackingLimits(int maxVectors, const std::vector &variables) { return CheckVariablesInPackingLimits(maxVectors, variables); } bool GetShaderStorageBlockRegister(const ShHandle handle, const std::string &shaderStorageBlockName, unsigned int *indexOut) { #ifdef ANGLE_ENABLE_HLSL ASSERT(indexOut); TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle); ASSERT(translator); if (!translator->hasShaderStorageBlock(shaderStorageBlockName)) { return false; } *indexOut = translator->getShaderStorageBlockRegister(shaderStorageBlockName); return true; #else return false; #endif // ANGLE_ENABLE_HLSL } bool GetUniformBlockRegister(const ShHandle handle, const std::string &uniformBlockName, unsigned int *indexOut) { #ifdef ANGLE_ENABLE_HLSL ASSERT(indexOut); TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle); ASSERT(translator); if (!translator->hasUniformBlock(uniformBlockName)) { return false; } *indexOut = translator->getUniformBlockRegister(uniformBlockName); return true; #else return false; #endif // ANGLE_ENABLE_HLSL } bool ShouldUniformBlockUseStructuredBuffer(const ShHandle handle, const std::string &uniformBlockName) { #ifdef ANGLE_ENABLE_HLSL TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle); ASSERT(translator); return translator->shouldUniformBlockUseStructuredBuffer(uniformBlockName); #else return false; #endif // ANGLE_ENABLE_HLSL } const std::map *GetUniformRegisterMap(const ShHandle handle) { #ifdef ANGLE_ENABLE_HLSL TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle); ASSERT(translator); return translator->getUniformRegisterMap(); #else return nullptr; #endif // ANGLE_ENABLE_HLSL } unsigned int GetReadonlyImage2DRegisterIndex(const ShHandle handle) { #ifdef ANGLE_ENABLE_HLSL TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle); ASSERT(translator); return translator->getReadonlyImage2DRegisterIndex(); #else return 0; #endif // ANGLE_ENABLE_HLSL } unsigned int GetImage2DRegisterIndex(const ShHandle handle) { #ifdef ANGLE_ENABLE_HLSL TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle); ASSERT(translator); return translator->getImage2DRegisterIndex(); #else return 0; #endif // ANGLE_ENABLE_HLSL } const std::set *GetUsedImage2DFunctionNames(const ShHandle handle) { #ifdef ANGLE_ENABLE_HLSL TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle); ASSERT(translator); return translator->getUsedImage2DFunctionNames(); #else return nullptr; #endif // ANGLE_ENABLE_HLSL } bool HasValidGeometryShaderInputPrimitiveType(const ShHandle handle) { ASSERT(handle); TShHandleBase *base = static_cast(handle); TCompiler *compiler = base->getAsCompiler(); ASSERT(compiler); return compiler->getGeometryShaderInputPrimitiveType() != EptUndefined; } bool HasValidGeometryShaderOutputPrimitiveType(const ShHandle handle) { ASSERT(handle); TShHandleBase *base = static_cast(handle); TCompiler *compiler = base->getAsCompiler(); ASSERT(compiler); return compiler->getGeometryShaderOutputPrimitiveType() != EptUndefined; } bool HasValidGeometryShaderMaxVertices(const ShHandle handle) { ASSERT(handle); TShHandleBase *base = static_cast(handle); TCompiler *compiler = base->getAsCompiler(); ASSERT(compiler); return compiler->getGeometryShaderMaxVertices() >= 0; } GLenum GetGeometryShaderInputPrimitiveType(const ShHandle handle) { ASSERT(handle); TShHandleBase *base = static_cast(handle); TCompiler *compiler = base->getAsCompiler(); ASSERT(compiler); return GetGeometryShaderPrimitiveTypeEnum(compiler->getGeometryShaderInputPrimitiveType()); } GLenum GetGeometryShaderOutputPrimitiveType(const ShHandle handle) { ASSERT(handle); TShHandleBase *base = static_cast(handle); TCompiler *compiler = base->getAsCompiler(); ASSERT(compiler); return GetGeometryShaderPrimitiveTypeEnum(compiler->getGeometryShaderOutputPrimitiveType()); } int GetGeometryShaderInvocations(const ShHandle handle) { ASSERT(handle); TShHandleBase *base = static_cast(handle); TCompiler *compiler = base->getAsCompiler(); ASSERT(compiler); return compiler->getGeometryShaderInvocations(); } int GetGeometryShaderMaxVertices(const ShHandle handle) { ASSERT(handle); TShHandleBase *base = static_cast(handle); TCompiler *compiler = base->getAsCompiler(); ASSERT(compiler); int maxVertices = compiler->getGeometryShaderMaxVertices(); ASSERT(maxVertices >= 0); return maxVertices; } unsigned int GetShaderSharedMemorySize(const ShHandle handle) { ASSERT(handle); TShHandleBase *base = static_cast(handle); TCompiler *compiler = base->getAsCompiler(); ASSERT(compiler); unsigned int sharedMemorySize = compiler->getSharedMemorySize(); return sharedMemorySize; } // Can't prefix with just _ because then we might introduce a double underscore, which is not safe // in GLSL (ESSL 3.00.6 section 3.8: All identifiers containing a double underscore are reserved for // use by the underlying implementation). u is short for user-defined. const char kUserDefinedNamePrefix[] = "_u"; namespace vk { // Interface block name containing the aggregate default uniforms const char kDefaultUniformsNameVS[] = "defaultUniformsVS"; const char kDefaultUniformsNameTCS[] = "defaultUniformsTCS"; const char kDefaultUniformsNameTES[] = "defaultUniformsTES"; const char kDefaultUniformsNameGS[] = "defaultUniformsGS"; const char kDefaultUniformsNameFS[] = "defaultUniformsFS"; const char kDefaultUniformsNameCS[] = "defaultUniformsCS"; // Interface block and variable names containing driver uniforms const char kDriverUniformsBlockName[] = "ANGLEUniformBlock"; const char kDriverUniformsVarName[] = "ANGLEUniforms"; // Interface block array name used for atomic counter emulation const char kAtomicCountersBlockName[] = "ANGLEAtomicCounters"; const char kLineRasterEmulationPosition[] = "ANGLEPosition"; } // namespace vk } // namespace sh