| // |
| // 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/glslang_wrapper.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; |
| |
| // glslang can only be initialized/finalized once per process. Otherwise, the following EGL commands |
| // will call GlslangFinalize() without ever being able to GlslangInitialize() again, leading to |
| // crashes since GlslangFinalize() cleans up glslang for the entire process. |
| // dpy1 = eglGetPlatformDisplay() | |
| // eglInitialize(dpy1) | GlslangInitialize() |
| // dpy2 = eglGetPlatformDisplay() | |
| // eglInitialize(dpy2) | GlslangInitialize() |
| // eglTerminate(dpy2) | GlslangFinalize() |
| // eglInitialize(dpy1) | Display::isInitialized() == true, no GlslangInitialize() |
| int initializeGlslangRefCount = 0; |
| |
| // |
| // This is the platform independent interface between an OGL driver |
| // and the shading language compiler. |
| // |
| |
| template <typename VarT> |
| const std::vector<VarT> *GetVariableList(const TCompiler *compiler); |
| |
| template <> |
| const std::vector<InterfaceBlock> *GetVariableList(const TCompiler *compiler) |
| { |
| return &compiler->getInterfaceBlocks(); |
| } |
| |
| TCompiler *GetCompilerFromHandle(ShHandle handle) |
| { |
| if (!handle) |
| { |
| return nullptr; |
| } |
| |
| TShHandleBase *base = static_cast<TShHandleBase *>(handle); |
| return base->getAsCompiler(); |
| } |
| |
| template <typename VarT> |
| const std::vector<VarT> *GetShaderVariables(const ShHandle handle) |
| { |
| TCompiler *compiler = GetCompilerFromHandle(handle); |
| if (!compiler) |
| { |
| return nullptr; |
| } |
| |
| return GetVariableList<VarT>(compiler); |
| } |
| |
| #ifdef ANGLE_ENABLE_HLSL |
| TranslatorHLSL *GetTranslatorHLSLFromHandle(ShHandle handle) |
| { |
| if (!handle) |
| return nullptr; |
| TShHandleBase *base = static_cast<TShHandleBase *>(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; |
| } |
| } |
| |
| GLenum GetTessellationShaderTypeEnum(sh::TLayoutTessEvaluationType type) |
| { |
| switch (type) |
| { |
| case EtetTriangles: |
| return GL_TRIANGLES; |
| case EtetQuads: |
| return GL_QUADS; |
| case EtetIsolines: |
| return GL_ISOLINES; |
| case EtetEqualSpacing: |
| return GL_EQUAL; |
| case EtetFractionalEvenSpacing: |
| return GL_FRACTIONAL_EVEN; |
| case EtetFractionalOddSpacing: |
| return GL_FRACTIONAL_ODD; |
| case EtetCw: |
| return GL_CW; |
| case EtetCcw: |
| return GL_CCW; |
| case EtetPointMode: |
| return GL_TESS_GEN_POINT_MODE; |
| |
| case EtetUndefined: |
| 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->EXT_shader_framebuffer_fetch = 0; |
| resources->EXT_shader_framebuffer_fetch_non_coherent = 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->OES_geometry_shader = 0; |
| resources->EXT_gpu_shader5 = 0; |
| resources->OES_shader_io_blocks = 0; |
| resources->EXT_shader_io_blocks = 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->ANGLE_base_vertex_base_instance_shader_builtin = 0; |
| resources->WEBGL_video_texture = 0; |
| resources->APPLE_clip_distance = 0; |
| resources->OES_texture_cube_map_array = 0; |
| resources->EXT_texture_cube_map_array = 0; |
| resources->EXT_shadow_samplers = 0; |
| resources->OES_shader_multisample_interpolation = 0; |
| resources->NV_draw_buffers = 0; |
| resources->OES_shader_image_atomic = 0; |
| resources->EXT_tessellation_shader = 0; |
| resources->OES_texture_buffer = 0; |
| resources->EXT_texture_buffer = 0; |
| resources->OES_sample_variables = 0; |
| resources->EXT_clip_cull_distance = 0; |
| |
| resources->MaxClipDistances = 8; |
| resources->MaxCullDistances = 8; |
| resources->MaxCombinedClipAndCullDistances = 8; |
| |
| // 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->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->MaxTessControlInputComponents = 64; |
| resources->MaxTessControlOutputComponents = 64; |
| resources->MaxTessControlTextureImageUnits = 16; |
| resources->MaxTessControlUniformComponents = 1024; |
| resources->MaxTessControlTotalOutputComponents = 2048; |
| resources->MaxTessControlImageUniforms = 0; |
| resources->MaxTessControlAtomicCounters = 0; |
| resources->MaxTessControlAtomicCounterBuffers = 0; |
| |
| resources->MaxTessPatchComponents = 120; |
| resources->MaxPatchVertices = 32; |
| resources->MaxTessGenLevel = 64; |
| |
| resources->MaxTessEvaluationInputComponents = 64; |
| resources->MaxTessEvaluationOutputComponents = 64; |
| resources->MaxTessEvaluationTextureImageUnits = 16; |
| resources->MaxTessEvaluationUniformComponents = 1024; |
| resources->MaxTessEvaluationImageUniforms = 0; |
| resources->MaxTessEvaluationAtomicCounters = 0; |
| resources->MaxTessEvaluationAtomicCounterBuffers = 0; |
| |
| resources->SubPixelBits = 8; |
| |
| resources->MaxSamples = 4; |
| } |
| |
| // |
| // 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<TShHandleBase *>(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<TShHandleBase *>(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(); |
| } |
| |
| // |
| // Return any object binary code. |
| // |
| const BinaryBlob &GetObjectBinaryBlob(const ShHandle handle) |
| { |
| TCompiler *compiler = GetCompilerFromHandle(handle); |
| ASSERT(compiler); |
| |
| TInfoSink &infoSink = compiler->getInfoSink(); |
| return infoSink.obj.getBinary(); |
| } |
| |
| const std::map<std::string, std::string> *GetNameHashingMap(const ShHandle handle) |
| { |
| TCompiler *compiler = GetCompilerFromHandle(handle); |
| ASSERT(compiler); |
| return &(compiler->getNameMap()); |
| } |
| |
| const std::vector<ShaderVariable> *GetUniforms(const ShHandle handle) |
| { |
| TCompiler *compiler = GetCompilerFromHandle(handle); |
| if (!compiler) |
| { |
| return nullptr; |
| } |
| return &compiler->getUniforms(); |
| } |
| |
| const std::vector<ShaderVariable> *GetInputVaryings(const ShHandle handle) |
| { |
| TCompiler *compiler = GetCompilerFromHandle(handle); |
| if (compiler == nullptr) |
| { |
| return nullptr; |
| } |
| return &compiler->getInputVaryings(); |
| } |
| |
| const std::vector<ShaderVariable> *GetOutputVaryings(const ShHandle handle) |
| { |
| TCompiler *compiler = GetCompilerFromHandle(handle); |
| if (compiler == nullptr) |
| { |
| return nullptr; |
| } |
| return &compiler->getOutputVaryings(); |
| } |
| |
| const std::vector<ShaderVariable> *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<ShaderVariable> *GetAttributes(const ShHandle handle) |
| { |
| TCompiler *compiler = GetCompilerFromHandle(handle); |
| if (!compiler) |
| { |
| return nullptr; |
| } |
| return &compiler->getAttributes(); |
| } |
| |
| const std::vector<ShaderVariable> *GetOutputVariables(const ShHandle handle) |
| { |
| TCompiler *compiler = GetCompilerFromHandle(handle); |
| if (!compiler) |
| { |
| return nullptr; |
| } |
| return &compiler->getOutputVariables(); |
| } |
| |
| const std::vector<InterfaceBlock> *GetInterfaceBlocks(const ShHandle handle) |
| { |
| return GetShaderVariables<InterfaceBlock>(handle); |
| } |
| |
| const std::vector<InterfaceBlock> *GetUniformBlocks(const ShHandle handle) |
| { |
| ASSERT(handle); |
| TShHandleBase *base = static_cast<TShHandleBase *>(handle); |
| TCompiler *compiler = base->getAsCompiler(); |
| ASSERT(compiler); |
| |
| return &compiler->getUniformBlocks(); |
| } |
| |
| const std::vector<InterfaceBlock> *GetShaderStorageBlocks(const ShHandle handle) |
| { |
| ASSERT(handle); |
| TShHandleBase *base = static_cast<TShHandleBase *>(handle); |
| TCompiler *compiler = base->getAsCompiler(); |
| ASSERT(compiler); |
| |
| return &compiler->getShaderStorageBlocks(); |
| } |
| |
| WorkGroupSize GetComputeShaderLocalGroupSize(const ShHandle handle) |
| { |
| ASSERT(handle); |
| |
| TShHandleBase *base = static_cast<TShHandleBase *>(handle); |
| TCompiler *compiler = base->getAsCompiler(); |
| ASSERT(compiler); |
| |
| return compiler->getComputeShaderLocalSize(); |
| } |
| |
| int GetVertexShaderNumViews(const ShHandle handle) |
| { |
| ASSERT(handle); |
| TShHandleBase *base = static_cast<TShHandleBase *>(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(); |
| } |
| |
| uint32_t GetShaderSpecConstUsageBits(const ShHandle handle) |
| { |
| TCompiler *compiler = GetCompilerFromHandle(handle); |
| if (compiler == nullptr) |
| { |
| return 0; |
| } |
| return compiler->getSpecConstUsageBits().bits(); |
| } |
| |
| bool CheckVariablesWithinPackingLimits(int maxVectors, const std::vector<ShaderVariable> &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<std::string, unsigned int> *GetUniformRegisterMap(const ShHandle handle) |
| { |
| #ifdef ANGLE_ENABLE_HLSL |
| TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle); |
| ASSERT(translator); |
| |
| return translator->getUniformRegisterMap(); |
| #else |
| return nullptr; |
| #endif // ANGLE_ENABLE_HLSL |
| } |
| |
| const std::set<std::string> *GetSlowCompilingUniformBlockSet(const ShHandle handle) |
| { |
| #ifdef ANGLE_ENABLE_HLSL |
| TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle); |
| ASSERT(translator); |
| |
| return translator->getSlowCompilingUniformBlockSet(); |
| #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<std::string> *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<TShHandleBase *>(handle); |
| TCompiler *compiler = base->getAsCompiler(); |
| ASSERT(compiler); |
| |
| return compiler->getGeometryShaderInputPrimitiveType() != EptUndefined; |
| } |
| |
| bool HasValidGeometryShaderOutputPrimitiveType(const ShHandle handle) |
| { |
| ASSERT(handle); |
| |
| TShHandleBase *base = static_cast<TShHandleBase *>(handle); |
| TCompiler *compiler = base->getAsCompiler(); |
| ASSERT(compiler); |
| |
| return compiler->getGeometryShaderOutputPrimitiveType() != EptUndefined; |
| } |
| |
| bool HasValidGeometryShaderMaxVertices(const ShHandle handle) |
| { |
| ASSERT(handle); |
| |
| TShHandleBase *base = static_cast<TShHandleBase *>(handle); |
| TCompiler *compiler = base->getAsCompiler(); |
| ASSERT(compiler); |
| |
| return compiler->getGeometryShaderMaxVertices() >= 0; |
| } |
| |
| bool HasValidTessGenMode(const ShHandle handle) |
| { |
| ASSERT(handle); |
| |
| TShHandleBase *base = static_cast<TShHandleBase *>(handle); |
| TCompiler *compiler = base->getAsCompiler(); |
| ASSERT(compiler); |
| |
| return compiler->getTessEvaluationShaderInputPrimitiveType() != EtetUndefined; |
| } |
| |
| bool HasValidTessGenSpacing(const ShHandle handle) |
| { |
| ASSERT(handle); |
| |
| TShHandleBase *base = static_cast<TShHandleBase *>(handle); |
| TCompiler *compiler = base->getAsCompiler(); |
| ASSERT(compiler); |
| |
| return compiler->getTessEvaluationShaderInputVertexSpacingType() != EtetUndefined; |
| } |
| |
| bool HasValidTessGenVertexOrder(const ShHandle handle) |
| { |
| ASSERT(handle); |
| |
| TShHandleBase *base = static_cast<TShHandleBase *>(handle); |
| TCompiler *compiler = base->getAsCompiler(); |
| ASSERT(compiler); |
| |
| return compiler->getTessEvaluationShaderInputOrderingType() != EtetUndefined; |
| } |
| |
| bool HasValidTessGenPointMode(const ShHandle handle) |
| { |
| ASSERT(handle); |
| |
| TShHandleBase *base = static_cast<TShHandleBase *>(handle); |
| TCompiler *compiler = base->getAsCompiler(); |
| ASSERT(compiler); |
| |
| return compiler->getTessEvaluationShaderInputPointType() != EtetUndefined; |
| } |
| |
| GLenum GetGeometryShaderInputPrimitiveType(const ShHandle handle) |
| { |
| ASSERT(handle); |
| |
| TShHandleBase *base = static_cast<TShHandleBase *>(handle); |
| TCompiler *compiler = base->getAsCompiler(); |
| ASSERT(compiler); |
| |
| return GetGeometryShaderPrimitiveTypeEnum(compiler->getGeometryShaderInputPrimitiveType()); |
| } |
| |
| GLenum GetGeometryShaderOutputPrimitiveType(const ShHandle handle) |
| { |
| ASSERT(handle); |
| |
| TShHandleBase *base = static_cast<TShHandleBase *>(handle); |
| TCompiler *compiler = base->getAsCompiler(); |
| ASSERT(compiler); |
| |
| return GetGeometryShaderPrimitiveTypeEnum(compiler->getGeometryShaderOutputPrimitiveType()); |
| } |
| |
| int GetGeometryShaderInvocations(const ShHandle handle) |
| { |
| ASSERT(handle); |
| |
| TShHandleBase *base = static_cast<TShHandleBase *>(handle); |
| TCompiler *compiler = base->getAsCompiler(); |
| ASSERT(compiler); |
| |
| return compiler->getGeometryShaderInvocations(); |
| } |
| |
| int GetGeometryShaderMaxVertices(const ShHandle handle) |
| { |
| ASSERT(handle); |
| |
| TShHandleBase *base = static_cast<TShHandleBase *>(handle); |
| TCompiler *compiler = base->getAsCompiler(); |
| ASSERT(compiler); |
| |
| int maxVertices = compiler->getGeometryShaderMaxVertices(); |
| ASSERT(maxVertices >= 0); |
| return maxVertices; |
| } |
| |
| int GetTessControlShaderVertices(const ShHandle handle) |
| { |
| ASSERT(handle); |
| |
| TShHandleBase *base = static_cast<TShHandleBase *>(handle); |
| TCompiler *compiler = base->getAsCompiler(); |
| ASSERT(compiler); |
| |
| int vertices = compiler->getTessControlShaderOutputVertices(); |
| return vertices; |
| } |
| |
| GLenum GetTessGenMode(const ShHandle handle) |
| { |
| ASSERT(handle); |
| |
| TShHandleBase *base = static_cast<TShHandleBase *>(handle); |
| TCompiler *compiler = base->getAsCompiler(); |
| ASSERT(compiler); |
| |
| return GetTessellationShaderTypeEnum(compiler->getTessEvaluationShaderInputPrimitiveType()); |
| } |
| |
| GLenum GetTessGenSpacing(const ShHandle handle) |
| { |
| ASSERT(handle); |
| |
| TShHandleBase *base = static_cast<TShHandleBase *>(handle); |
| TCompiler *compiler = base->getAsCompiler(); |
| ASSERT(compiler); |
| |
| return GetTessellationShaderTypeEnum(compiler->getTessEvaluationShaderInputVertexSpacingType()); |
| } |
| |
| GLenum GetTessGenVertexOrder(const ShHandle handle) |
| { |
| ASSERT(handle); |
| |
| TShHandleBase *base = static_cast<TShHandleBase *>(handle); |
| TCompiler *compiler = base->getAsCompiler(); |
| ASSERT(compiler); |
| |
| return GetTessellationShaderTypeEnum(compiler->getTessEvaluationShaderInputOrderingType()); |
| } |
| |
| GLenum GetTessGenPointMode(const ShHandle handle) |
| { |
| ASSERT(handle); |
| |
| TShHandleBase *base = static_cast<TShHandleBase *>(handle); |
| TCompiler *compiler = base->getAsCompiler(); |
| ASSERT(compiler); |
| |
| return GetTessellationShaderTypeEnum(compiler->getTessEvaluationShaderInputPointType()); |
| } |
| |
| unsigned int GetShaderSharedMemorySize(const ShHandle handle) |
| { |
| ASSERT(handle); |
| |
| TShHandleBase *base = static_cast<TShHandleBase *>(handle); |
| TCompiler *compiler = base->getAsCompiler(); |
| ASSERT(compiler); |
| |
| unsigned int sharedMemorySize = compiler->getSharedMemorySize(); |
| return sharedMemorySize; |
| } |
| |
| void InitializeGlslang() |
| { |
| if (initializeGlslangRefCount == 0) |
| { |
| GlslangInitialize(); |
| } |
| ++initializeGlslangRefCount; |
| ASSERT(initializeGlslangRefCount < std::numeric_limits<int>::max()); |
| } |
| |
| void FinalizeGlslang() |
| { |
| --initializeGlslangRefCount; |
| ASSERT(initializeGlslangRefCount >= 0); |
| if (initializeGlslangRefCount == 0) |
| { |
| GlslangFinalize(); |
| } |
| } |
| |
| // 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"; |
| |
| const char kXfbEmulationGetOffsetsFunctionName[] = "ANGLEGetXfbOffsets"; |
| const char kXfbEmulationCaptureFunctionName[] = "ANGLECaptureXfb"; |
| const char kXfbEmulationBufferBlockName[] = "ANGLEXfbBuffer"; |
| const char kXfbEmulationBufferName[] = "ANGLEXfb"; |
| const char kXfbEmulationBufferFieldName[] = "xfbOut"; |
| |
| const char kXfbExtensionPositionOutName[] = "ANGLEXfbPosition"; |
| |
| // EXT_shader_framebuffer_fetch / EXT_shader_framebuffer_fetch_non_coherent |
| const char kInputAttachmentName[] = "ANGLEInputAttachment"; |
| |
| } // namespace vk |
| |
| const char *BlockLayoutTypeToString(BlockLayoutType type) |
| { |
| switch (type) |
| { |
| case BlockLayoutType::BLOCKLAYOUT_STD140: |
| return "std140"; |
| case BlockLayoutType::BLOCKLAYOUT_STD430: |
| return "std430"; |
| case BlockLayoutType::BLOCKLAYOUT_PACKED: |
| return "packed"; |
| case BlockLayoutType::BLOCKLAYOUT_SHARED: |
| return "shared"; |
| default: |
| return "invalid"; |
| } |
| } |
| |
| const char *BlockTypeToString(BlockType type) |
| { |
| switch (type) |
| { |
| case BlockType::BLOCK_BUFFER: |
| return "buffer"; |
| case BlockType::BLOCK_UNIFORM: |
| return "uniform"; |
| default: |
| return "invalid"; |
| } |
| } |
| |
| const char *InterpolationTypeToString(InterpolationType type) |
| { |
| switch (type) |
| { |
| case InterpolationType::INTERPOLATION_SMOOTH: |
| return "smooth"; |
| case InterpolationType::INTERPOLATION_CENTROID: |
| return "centroid"; |
| case InterpolationType::INTERPOLATION_SAMPLE: |
| return "sample"; |
| case InterpolationType::INTERPOLATION_FLAT: |
| return "flat"; |
| case InterpolationType::INTERPOLATION_NOPERSPECTIVE: |
| return "noperspective"; |
| default: |
| return "invalid"; |
| } |
| } |
| } // namespace sh |