Edit

kc3-lang/angle/src/compiler/translator/ValidateGlobalInitializer.cpp

Branch :

  • Show log

    Commit

  • Author : Mohan Maiya
    Date : 2020-03-19 16:30:21
    Hash : ca2b6e1f
    Message : Vulkan: Implement EXT_shader_non_constant_global_initializers Enables the translator to handle non-constant global initializers in all essl versions iff the shader enables the extension to do so. Bug: angleproject:4468 Test: angle_end2end_tests --gtest_filter=ShaderNonConstGlobalInitializerTest.* Change-Id: I8f138c12fc83d2f38ff8f45ca9133222b01e4087 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2102959 Reviewed-by: Tobin Ehlis <tobine@google.com> Reviewed-by: Jamie Madill <jmadill@chromium.org> Commit-Queue: Mohan Maiya <m.maiya@samsung.com>

  • src/compiler/translator/ValidateGlobalInitializer.cpp
  • //
    // 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.
    //
    
    #include "compiler/translator/ValidateGlobalInitializer.h"
    
    #include "compiler/translator/tree_util/IntermTraverse.h"
    
    namespace sh
    {
    
    namespace
    {
    
    const int kMaxAllowedTraversalDepth = 256;
    
    class ValidateGlobalInitializerTraverser : public TIntermTraverser
    {
      public:
        ValidateGlobalInitializerTraverser(int shaderVersion,
                                           bool isWebGL,
                                           bool hasExtNonConstGlobalInitializers);
    
        void visitSymbol(TIntermSymbol *node) override;
        void visitConstantUnion(TIntermConstantUnion *node) override;
        bool visitAggregate(Visit visit, TIntermAggregate *node) override;
        bool visitBinary(Visit visit, TIntermBinary *node) override;
        bool visitUnary(Visit visit, TIntermUnary *node) override;
    
        bool isValid() const { return mIsValid && mMaxDepth < mMaxAllowedDepth; }
        bool issueWarning() const { return mIssueWarning; }
    
      private:
        ANGLE_INLINE void onNonConstInitializerVisit(bool accept)
        {
            if (accept)
            {
                if (!mExtNonConstGlobalInitializers)
                {
                    mIssueWarning = true;
                }
            }
            else
            {
                mIsValid = false;
            }
        }
    
        int mShaderVersion;
        bool mIsWebGL;
        bool mExtNonConstGlobalInitializers;
        bool mIsValid;
        bool mIssueWarning;
    };
    
    void ValidateGlobalInitializerTraverser::visitSymbol(TIntermSymbol *node)
    {
        // ESSL 1.00 section 4.3 (or ESSL 3.00 section 4.3):
        // Global initializers must be constant expressions.
        switch (node->getType().getQualifier())
        {
            case EvqConst:
                break;
            case EvqGlobal:
            case EvqTemporary:
            case EvqUniform:
                // We allow these cases to be compatible with legacy ESSL 1.00 content.
                // Implement stricter rules for ESSL 3.00 since there's no legacy content to deal
                // with.
                onNonConstInitializerVisit(mExtNonConstGlobalInitializers ||
                                           ((mShaderVersion < 300) && mIsWebGL));
                break;
            default:
                mIsValid = false;
        }
    }
    
    void ValidateGlobalInitializerTraverser::visitConstantUnion(TIntermConstantUnion *node)
    {
        // Constant unions that are not constant expressions may result from folding a ternary
        // expression.
        switch (node->getType().getQualifier())
        {
            case EvqConst:
                break;
            case EvqTemporary:
                onNonConstInitializerVisit(mExtNonConstGlobalInitializers ||
                                           ((mShaderVersion < 300) && mIsWebGL));
                break;
            default:
                UNREACHABLE();
        }
    }
    
    bool ValidateGlobalInitializerTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
    {
        // Disallow calls to user-defined functions and texture lookup functions in global variable
        // initializers.
        // This is done simply by disabling all function calls - built-in math functions don't use
        // the function call ops.
        if (node->isFunctionCall())
        {
            onNonConstInitializerVisit(mExtNonConstGlobalInitializers);
        }
        return true;
    }
    
    bool ValidateGlobalInitializerTraverser::visitBinary(Visit visit, TIntermBinary *node)
    {
        if (node->isAssignment())
        {
            onNonConstInitializerVisit(mExtNonConstGlobalInitializers);
        }
        return true;
    }
    
    bool ValidateGlobalInitializerTraverser::visitUnary(Visit visit, TIntermUnary *node)
    {
        if (node->isAssignment())
        {
            onNonConstInitializerVisit(mExtNonConstGlobalInitializers);
        }
        return true;
    }
    
    ValidateGlobalInitializerTraverser::ValidateGlobalInitializerTraverser(
        int shaderVersion,
        bool isWebGL,
        bool hasExtNonConstGlobalInitializers)
        : TIntermTraverser(true, false, false, nullptr),
          mShaderVersion(shaderVersion),
          mIsWebGL(isWebGL),
          mExtNonConstGlobalInitializers(hasExtNonConstGlobalInitializers),
          mIsValid(true),
          mIssueWarning(false)
    {
        setMaxAllowedDepth(kMaxAllowedTraversalDepth);
    }
    
    }  // namespace
    
    bool ValidateGlobalInitializer(TIntermTyped *initializer,
                                   int shaderVersion,
                                   bool isWebGL,
                                   bool hasExtNonConstGlobalInitializers,
                                   bool *warning)
    {
        ValidateGlobalInitializerTraverser validate(shaderVersion, isWebGL,
                                                    hasExtNonConstGlobalInitializers);
        initializer->traverse(&validate);
        ASSERT(warning != nullptr);
        *warning = validate.issueWarning();
        return validate.isValid();
    }
    
    }  // namespace sh