Edit

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

Branch :

  • Show log

    Commit

  • Author : Kimmo Kinnunen
    Date : 2015-07-16 14:13:11
    Hash : b18609b9
    Message : Implement ES 2,3 parts of EXT_blend_func_extended for shader translation Exposes gl_SecondaryFragColor, glSecondaryFragData[] and gl_MaxDualSourceDrawBuffers to GLES SL 1.0. Relaxes rules for undefined output locations for GLES SL 3.0 and exposes gl_MaxDualSourceDrawBuffers. If the output GL context is GL ES 2.0 or 3.0: The emulation layer is expected to turn on EXT_blend_func_extended if the output GL context supports it. If the output GL context is GL: The emulation layer is expected to turn on EXT_blend_func_extended if the output GL context supports ARB_blend_func_extended or if GL context is 3.2 or later. If the source shader spec is GLES SL 2.0: The emulation layer is expected to inspect the shader compilation output variables upon linking. If output target is GL SL, the emulation layer should bind color location 0, index 1 to "angle_SecondaryFragColor" if variable "gl_SecondaryFragColorEXT" is used. Alternatively, emulation layer should bind "angle_SecondaryFragData" to locations 0,1,2,3,..., all color index 1, if "gl_SecondaryFragData" array is used. (The caller can not bind the locations or specify output variables.) If the source shader spec is GLES SL 3.0: The emulation layer is expected to do location auto-resolve of the the output variables that have undefined output locations that have not been bound by the caller. (The caller can not use gl_ built-ins, so nothing to do with those.) BUG=angleproject:1085 TEST=angle_unittest Change-Id: I5cafe205b0c29478b0dcd24aa89a7b0000f5d046 Reviewed-on: https://chromium-review.googlesource.com/287580 Reviewed-by: Zhenyao Mo <zmo@chromium.org> Reviewed-by: Jamie Madill <jmadill@chromium.org> Tested-by: Kimmo Kinnunen <kkinnunen@nvidia.com>

  • src/compiler/translator/ValidateOutputs.cpp
  • //
    // Copyright (c) 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/ValidateOutputs.h"
    #include "compiler/translator/InfoSink.h"
    #include "compiler/translator/InitializeParseContext.h"
    #include "compiler/translator/ParseContext.h"
    
    namespace
    {
    void error(int *errorCount, TInfoSinkBase &sink, const TIntermSymbol &symbol, const char *reason)
    {
        sink.prefix(EPrefixError);
        sink.location(symbol.getLine());
        sink << "'" << symbol.getSymbol() << "' : " << reason << "\n";
        (*errorCount)++;
    }
    
    }  // namespace
    
    ValidateOutputs::ValidateOutputs(const TExtensionBehavior &extBehavior, int maxDrawBuffers)
        : TIntermTraverser(true, false, false),
          mMaxDrawBuffers(maxDrawBuffers),
          mAllowUnspecifiedOutputLocationResolution(
              IsExtensionEnabled(extBehavior, "GL_EXT_blend_func_extended"))
    {
    }
    
    void ValidateOutputs::visitSymbol(TIntermSymbol *symbol)
    {
        TString name = symbol->getSymbol();
        TQualifier qualifier = symbol->getQualifier();
    
        if (mVisitedSymbols.count(name) == 1)
            return;
    
        mVisitedSymbols.insert(name);
    
        if (qualifier == EvqFragmentOut)
        {
            if (symbol->getType().getLayoutQualifier().location == -1)
            {
                mUnspecifiedLocationOutputs.push_back(symbol);
            }
            else
            {
                mOutputs.push_back(symbol);
            }
        }
    }
    
    int ValidateOutputs::validateAndCountErrors(TInfoSinkBase &sink) const
    {
        OutputVector validOutputs(mMaxDrawBuffers);
        int errorCount = 0;
    
        for (const auto &symbol : mOutputs)
        {
            const TType &type         = symbol->getType();
            const size_t elementCount = static_cast<size_t>(type.isArray() ? type.getArraySize() : 1);
            const size_t location     = static_cast<size_t>(type.getLayoutQualifier().location);
    
            ASSERT(type.getLayoutQualifier().location != -1);
    
            if (location + elementCount <= validOutputs.size())
            {
                for (size_t elementIndex = 0; elementIndex < elementCount; elementIndex++)
                {
                    const size_t offsetLocation = location + elementIndex;
                    if (validOutputs[offsetLocation])
                    {
                        std::stringstream strstr;
                        strstr << "conflicting output locations with previously defined output '"
                               << validOutputs[offsetLocation]->getSymbol() << "'";
                        error(&errorCount, sink, *symbol, strstr.str().c_str());
                    }
                    else
                    {
                        validOutputs[offsetLocation] = symbol;
                    }
                }
            }
            else
            {
                if (elementCount > 0)
                {
                    error(&errorCount, sink, *symbol,
                          elementCount > 1 ? "output array locations would exceed MAX_DRAW_BUFFERS"
                                           : "output location must be < MAX_DRAW_BUFFERS");
                }
            }
        }
    
        if (!mAllowUnspecifiedOutputLocationResolution &&
            ((!mOutputs.empty() && !mUnspecifiedLocationOutputs.empty()) ||
             mUnspecifiedLocationOutputs.size() > 1))
        {
            for (const auto &symbol : mUnspecifiedLocationOutputs)
            {
                error(&errorCount, sink, *symbol,
                      "must explicitly specify all locations when using multiple fragment outputs");
            }
        }
        return errorCount;
    }