Edit

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

Branch :

  • Show log

    Commit

  • Author : Olli Etuaho
    Date : 2015-06-18 15:47:46
    Hash : 5d91dda9
    Message : Remove dynamic indexing of matrices and vectors in HLSL Re-re-relanding after clang warning fix. Re-re-landing with fix to setting qualifiers on generated nodes. The previous version failed when a uniform was indexed, because it would set the uniform qualifier on some of the generated nodes and that interfered with the operation of UniformsHLSL. Re-landing after fixing D3D9 specific issues. HLSL doesn't support dynamic indexing of matrices and vectors, so replace that with helper functions that unroll dynamic indexing into switch/case and static indexing. Both the indexed vector/matrix expression and the index may have side effects, and these will be evaluated correctly. If necessary, index expressions that have side effects will be written to a temporary variable that will replace the index. Besides dEQP tests, this change is tested by a WebGL 2 conformance test. In the case that a dynamic index is out-of-range, the base ESSL 3.00 spec allows undefined behavior. KHR_robust_buffer_access_behavior adds the requirement that program termination should not occur and that out-of-range reads must return either a value from the active program's memory or zero, and out-of-range writes should only affect the active program's memory or do nothing. This patch clamps out-of-range indices so that either the first or last item of the matrix/vector is accessed. The code is not transformed in case the it fits within the limited subset of ESSL 1.00 given in Appendix A of the spec. If the code isn't within the restricted subset, even ESSL 1.00 shaders may require this workaround. BUG=angleproject:1116 TEST=dEQP-GLES3.functional.shaders.indexing.* (all pass after change) WebGL 2 conformance tests (glsl3/vector-dynamic-indexing.html) Change-Id: I9f6d7c7ecda8ac4dc3c30b39e15a9a0b5381c5a8 Reviewed-on: https://chromium-review.googlesource.com/310010 Reviewed-by: Geoff Lang <geofflang@chromium.org> Tested-by: Geoff Lang <geofflang@chromium.org>

  • src/compiler/translator/TranslatorHLSL.cpp
  • //
    // 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.
    //
    
    #include "compiler/translator/TranslatorHLSL.h"
    
    #include "compiler/translator/ArrayReturnValueToOutParameter.h"
    #include "compiler/translator/OutputHLSL.h"
    #include "compiler/translator/RemoveDynamicIndexing.h"
    #include "compiler/translator/RewriteElseBlocks.h"
    #include "compiler/translator/SeparateArrayInitialization.h"
    #include "compiler/translator/SeparateDeclarations.h"
    #include "compiler/translator/SeparateExpressionsReturningArrays.h"
    #include "compiler/translator/UnfoldShortCircuitToIf.h"
    
    TranslatorHLSL::TranslatorHLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)
        : TCompiler(type, spec, output)
    {
    }
    
    void TranslatorHLSL::translate(TIntermNode *root, int compileOptions)
    {
        const ShBuiltInResources &resources = getResources();
        int numRenderTargets = resources.EXT_draw_buffers ? resources.MaxDrawBuffers : 1;
    
        SeparateDeclarations(root);
    
        // Note that SeparateDeclarations needs to be run before UnfoldShortCircuitToIf.
        UnfoldShortCircuitToIf(root, getTemporaryIndex());
    
        SeparateExpressionsReturningArrays(root, getTemporaryIndex());
    
        // Note that SeparateDeclarations needs to be run before SeparateArrayInitialization.
        SeparateArrayInitialization(root);
    
        // 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.
        ArrayReturnValueToOutParameter(root, getTemporaryIndex());
    
        if (!shouldRunLoopAndIndexingValidation(compileOptions))
        {
            // HLSL doesn't support dynamic indexing of vectors and matrices.
            RemoveDynamicIndexing(root, getTemporaryIndex(), getSymbolTable(), getShaderVersion());
        }
    
        // 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_HLSL9_OUTPUT && getShaderType() == GL_VERTEX_SHADER)
        {
            sh::RewriteElseBlocks(root, getTemporaryIndex());
        }
    
        sh::OutputHLSL outputHLSL(getShaderType(), getShaderVersion(), getExtensionBehavior(),
            getSourcePath(), getOutputType(), numRenderTargets, getUniforms(), compileOptions);
    
        outputHLSL.output(root, getInfoSink().obj);
    
        mInterfaceBlockRegisterMap = outputHLSL.getInterfaceBlockRegisterMap();
        mUniformRegisterMap = outputHLSL.getUniformRegisterMap();
    }
    
    bool TranslatorHLSL::hasInterfaceBlock(const std::string &interfaceBlockName) const
    {
        return (mInterfaceBlockRegisterMap.count(interfaceBlockName) > 0);
    }
    
    unsigned int TranslatorHLSL::getInterfaceBlockRegister(const std::string &interfaceBlockName) const
    {
        ASSERT(hasInterfaceBlock(interfaceBlockName));
        return mInterfaceBlockRegisterMap.find(interfaceBlockName)->second;
    }
    
    bool TranslatorHLSL::hasUniform(const std::string &uniformName) const
    {
        return (mUniformRegisterMap.count(uniformName) > 0);
    }
    
    unsigned int TranslatorHLSL::getUniformRegister(const std::string &uniformName) const
    {
        ASSERT(hasUniform(uniformName));
        return mUniformRegisterMap.find(uniformName)->second;
    }