Edit

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

Branch :

  • Show log

    Commit

  • Author : jchen10
    Date : 2019-10-18 16:01:34
    Hash : b3070102
    Message : Add SH_REMOVE_DYNAMIC_INDEXING_OF_SWIZZLED_VECTOR This is a workaround for the webgl2 conformance test case WebglConformance_conformance2_glsl3_vector_dynamic_indexing_swizzled_lvalue. Dynamic indexing of swizzled lvalue like "v.zyx[i] = 0.0" is problematic on various platforms. This removes the indexing by translating it this way: void dyn_index_write_vec3(inout vec3 base, in int index, in float value){ switch (index) { case (0): (base[0] = value); return ; case (1): (base[1] = value); return ; case (2): (base[2] = value); return ; default: break; } if ((index < 0)) { (base[0] = value); return ; } { (base[2] = value); } } ... dyn_index_write_vec3(v.zyx, i, 0.0); ... Bug: chromium:709351 Change-Id: I971b38eb404209b56e6764af1063878c078a7e88 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1869109 Commit-Queue: Jie A Chen <jie.a.chen@intel.com> Reviewed-by: Geoff Lang <geofflang@chromium.org>

  • src/compiler/translator/TranslatorHLSL.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/TranslatorHLSL.h"
    
    #include "compiler/translator/OutputHLSL.h"
    #include "compiler/translator/tree_ops/AddDefaultReturnStatements.h"
    #include "compiler/translator/tree_ops/ArrayReturnValueToOutParameter.h"
    #include "compiler/translator/tree_ops/BreakVariableAliasingInInnerLoops.h"
    #include "compiler/translator/tree_ops/EmulatePrecision.h"
    #include "compiler/translator/tree_ops/ExpandIntegerPowExpressions.h"
    #include "compiler/translator/tree_ops/PruneEmptyCases.h"
    #include "compiler/translator/tree_ops/RemoveDynamicIndexing.h"
    #include "compiler/translator/tree_ops/RewriteAtomicFunctionExpressions.h"
    #include "compiler/translator/tree_ops/RewriteElseBlocks.h"
    #include "compiler/translator/tree_ops/RewriteExpressionsWithShaderStorageBlock.h"
    #include "compiler/translator/tree_ops/RewriteTexelFetchOffset.h"
    #include "compiler/translator/tree_ops/RewriteUnaryMinusOperatorInt.h"
    #include "compiler/translator/tree_ops/SeparateArrayConstructorStatements.h"
    #include "compiler/translator/tree_ops/SeparateArrayInitialization.h"
    #include "compiler/translator/tree_ops/SeparateDeclarations.h"
    #include "compiler/translator/tree_ops/SeparateExpressionsReturningArrays.h"
    #include "compiler/translator/tree_ops/SimplifyLoopConditions.h"
    #include "compiler/translator/tree_ops/SplitSequenceOperator.h"
    #include "compiler/translator/tree_ops/UnfoldShortCircuitToIf.h"
    #include "compiler/translator/tree_ops/WrapSwitchStatementsInBlocks.h"
    #include "compiler/translator/tree_util/IntermNodePatternMatcher.h"
    
    namespace sh
    {
    
    TranslatorHLSL::TranslatorHLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)
        : TCompiler(type, spec, output)
    {}
    
    bool TranslatorHLSL::translate(TIntermBlock *root,
                                   ShCompileOptions compileOptions,
                                   PerformanceDiagnostics *perfDiagnostics)
    {
        const ShBuiltInResources &resources = getResources();
        int numRenderTargets                = resources.EXT_draw_buffers ? resources.MaxDrawBuffers : 1;
        int maxDualSourceDrawBuffers =
            resources.EXT_blend_func_extended ? resources.MaxDualSourceDrawBuffers : 0;
    
        if (!sh::AddDefaultReturnStatements(this, root))
        {
            return false;
        }
    
        // Note that SimplifyLoopConditions needs to be run before any other AST transformations that
        // may need to generate new statements from loop conditions or loop expressions.
        // Note that SeparateDeclarations has already been run in TCompiler::compileTreeImpl().
        if (!SimplifyLoopConditions(
                this, root,
                IntermNodePatternMatcher::kExpressionReturningArray |
                    IntermNodePatternMatcher::kUnfoldedShortCircuitExpression |
                    IntermNodePatternMatcher::kDynamicIndexingOfVectorOrMatrixInLValue,
                &getSymbolTable()))
        {
            return false;
        }
    
        if (!SplitSequenceOperator(
                this, root,
                IntermNodePatternMatcher::kExpressionReturningArray |
                    IntermNodePatternMatcher::kUnfoldedShortCircuitExpression |
                    IntermNodePatternMatcher::kDynamicIndexingOfVectorOrMatrixInLValue,
                &getSymbolTable()))
        {
            return false;
        }
    
        // Note that SeparateDeclarations needs to be run before UnfoldShortCircuitToIf.
        if (!UnfoldShortCircuitToIf(this, root, &getSymbolTable()))
        {
            return false;
        }
    
        if (!SeparateArrayConstructorStatements(this, root))
        {
            return false;
        }
    
        if (!SeparateExpressionsReturningArrays(this, root, &getSymbolTable()))
        {
            return false;
        }
    
        // Note that SeparateDeclarations needs to be run before SeparateArrayInitialization.
        if (!SeparateArrayInitialization(this, root))
        {
            return false;
        }
    
        // HLSL doesn't support arrays as return values, we'll need to make functions that have an array
        // as a return value to use an out parameter to transfer the array data instead.
        if (!ArrayReturnValueToOutParameter(this, root, &getSymbolTable()))
        {
            return false;
        }
    
        if (!shouldRunLoopAndIndexingValidation(compileOptions))
        {
            // HLSL doesn't support dynamic indexing of vectors and matrices.
            if (!RemoveDynamicIndexingOfNonSSBOVectorOrMatrix(this, root, &getSymbolTable(),
                                                              perfDiagnostics))
            {
                return false;
            }
        }
    
        // Work around D3D9 bug that would manifest in vertex shaders with selection blocks which
        // use a vertex attribute as a condition, and some related computation in the else block.
        if (getOutputType() == SH_HLSL_3_0_OUTPUT && getShaderType() == GL_VERTEX_SHADER)
        {
            if (!sh::RewriteElseBlocks(this, root, &getSymbolTable()))
            {
                return false;
            }
        }
    
        // Work around an HLSL compiler frontend aliasing optimization bug.
        // TODO(cwallez) The date is 2016-08-25, Microsoft said the bug would be fixed
        // in the next release of d3dcompiler.dll, it would be nice to detect the DLL
        // version and only apply the workaround if it is too old.
        if (!sh::BreakVariableAliasingInInnerLoops(this, root))
        {
            return false;
        }
    
        // WrapSwitchStatementsInBlocks should be called after any AST transformations that might
        // introduce variable declarations inside the main scope of any switch statement. It cannot
        // result in no-op cases at the end of switch statements, because unreferenced variables
        // have already been pruned.
        if (!WrapSwitchStatementsInBlocks(this, root))
        {
            return false;
        }
    
        bool precisionEmulation =
            getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision;
    
        if (precisionEmulation)
        {
            EmulatePrecision emulatePrecision(&getSymbolTable());
            root->traverse(&emulatePrecision);
            if (!emulatePrecision.updateTree(this, root))
            {
                return false;
            }
            emulatePrecision.writeEmulationHelpers(getInfoSink().obj, getShaderVersion(),
                                                   getOutputType());
        }
    
        if ((compileOptions & SH_EXPAND_SELECT_HLSL_INTEGER_POW_EXPRESSIONS) != 0)
        {
            if (!sh::ExpandIntegerPowExpressions(this, root, &getSymbolTable()))
            {
                return false;
            }
        }
    
        if ((compileOptions & SH_REWRITE_TEXELFETCHOFFSET_TO_TEXELFETCH) != 0)
        {
            if (!sh::RewriteTexelFetchOffset(this, root, getSymbolTable(), getShaderVersion()))
            {
                return false;
            }
        }
    
        if (((compileOptions & SH_REWRITE_INTEGER_UNARY_MINUS_OPERATOR) != 0) &&
            getShaderType() == GL_VERTEX_SHADER)
        {
            if (!sh::RewriteUnaryMinusOperatorInt(this, root))
            {
                return false;
            }
        }
    
        if (getShaderVersion() >= 310)
        {
            // Due to ssbo also can be used as the argument of atomic memory functions, we should put
            // RewriteExpressionsWithShaderStorageBlock before RewriteAtomicFunctionExpressions.
            if (!sh::RewriteExpressionsWithShaderStorageBlock(this, root, &getSymbolTable()))
            {
                return false;
            }
            if (!sh::RewriteAtomicFunctionExpressions(this, root, &getSymbolTable(),
                                                      getShaderVersion()))
            {
                return false;
            }
        }
    
        sh::OutputHLSL outputHLSL(getShaderType(), getShaderSpec(), getShaderVersion(),
                                  getExtensionBehavior(), getSourcePath(), getOutputType(),
                                  numRenderTargets, maxDualSourceDrawBuffers, getUniforms(),
                                  compileOptions, getComputeShaderLocalSize(), &getSymbolTable(),
                                  perfDiagnostics, mShaderStorageBlocks);
    
        outputHLSL.output(root, getInfoSink().obj);
    
        mShaderStorageBlockRegisterMap = outputHLSL.getShaderStorageBlockRegisterMap();
        mUniformBlockRegisterMap       = outputHLSL.getUniformBlockRegisterMap();
        mUniformRegisterMap            = outputHLSL.getUniformRegisterMap();
        mReadonlyImage2DRegisterIndex  = outputHLSL.getReadonlyImage2DRegisterIndex();
        mImage2DRegisterIndex          = outputHLSL.getImage2DRegisterIndex();
        mUsedImage2DFunctionNames      = outputHLSL.getUsedImage2DFunctionNames();
    
        return true;
    }
    
    bool TranslatorHLSL::shouldFlattenPragmaStdglInvariantAll()
    {
        // Not necessary when translating to HLSL.
        return false;
    }
    
    bool TranslatorHLSL::hasShaderStorageBlock(const std::string &uniformBlockName) const
    {
        return (mShaderStorageBlockRegisterMap.count(uniformBlockName) > 0);
    }
    
    unsigned int TranslatorHLSL::getShaderStorageBlockRegister(
        const std::string &shaderStorageBlockName) const
    {
        ASSERT(hasShaderStorageBlock(shaderStorageBlockName));
        return mShaderStorageBlockRegisterMap.find(shaderStorageBlockName)->second;
    }
    
    bool TranslatorHLSL::hasUniformBlock(const std::string &uniformBlockName) const
    {
        return (mUniformBlockRegisterMap.count(uniformBlockName) > 0);
    }
    
    unsigned int TranslatorHLSL::getUniformBlockRegister(const std::string &uniformBlockName) const
    {
        ASSERT(hasUniformBlock(uniformBlockName));
        return mUniformBlockRegisterMap.find(uniformBlockName)->second;
    }
    
    const std::map<std::string, unsigned int> *TranslatorHLSL::getUniformRegisterMap() const
    {
        return &mUniformRegisterMap;
    }
    
    unsigned int TranslatorHLSL::getReadonlyImage2DRegisterIndex() const
    {
        return mReadonlyImage2DRegisterIndex;
    }
    
    unsigned int TranslatorHLSL::getImage2DRegisterIndex() const
    {
        return mImage2DRegisterIndex;
    }
    
    const std::set<std::string> *TranslatorHLSL::getUsedImage2DFunctionNames() const
    {
        return &mUsedImage2DFunctionNames;
    }
    
    }  // namespace sh