Edit

kc3-lang/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.cpp

Branch :

  • Show log

    Commit

  • Author : Corentin Wallez
    Date : 2015-12-07 15:54:17
    Hash : e678b66c
    Message : TDependencyGraph: use range-base for loops instead of iterators No functional changes intended. BUG=angleproject:591 Change-Id: Ieccf0b792766be86a3533e5324ce6f83ee508ad5 Reviewed-on: https://chromium-review.googlesource.com/316601 Reviewed-by: Jamie Madill <jmadill@chromium.org> Reviewed-by: Geoff Lang <geofflang@chromium.org> Tested-by: Corentin Wallez <cwallez@chromium.org>

  • src/compiler/translator/timing/RestrictFragmentShaderTiming.cpp
  • //
    // Copyright (c) 2012 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/InfoSink.h"
    #include "compiler/translator/ParseContext.h"
    #include "compiler/translator/depgraph/DependencyGraphOutput.h"
    #include "compiler/translator/timing/RestrictFragmentShaderTiming.h"
    
    RestrictFragmentShaderTiming::RestrictFragmentShaderTiming(TInfoSinkBase& sink)
        : mSink(sink)
        , mNumErrors(0)
    {
        // Sampling ops found only in fragment shaders.
        mSamplingOps.insert("texture2D(s21;vf2;f1;");
        mSamplingOps.insert("texture2DProj(s21;vf3;f1;");
        mSamplingOps.insert("texture2DProj(s21;vf4;f1;");
        mSamplingOps.insert("textureCube(sC1;vf3;f1;");
        // Sampling ops found in both vertex and fragment shaders.
        mSamplingOps.insert("texture2D(s21;vf2;");
        mSamplingOps.insert("texture2DProj(s21;vf3;");
        mSamplingOps.insert("texture2DProj(s21;vf4;");
        mSamplingOps.insert("textureCube(sC1;vf3;");
        // Sampling ops provided by OES_EGL_image_external.
        mSamplingOps.insert("texture2D(1;vf2;");
        mSamplingOps.insert("texture2DProj(1;vf3;");
        mSamplingOps.insert("texture2DProj(1;vf4;");
        // Sampling ops provided by ARB_texture_rectangle.
        mSamplingOps.insert("texture2DRect(1;vf2;");
        mSamplingOps.insert("texture2DRectProj(1;vf3;");
        mSamplingOps.insert("texture2DRectProj(1;vf4;");
        // Sampling ops provided by EXT_shader_texture_lod.
        mSamplingOps.insert("texture2DLodEXT(1;vf2;f1;");
        mSamplingOps.insert("texture2DProjLodEXT(1;vf3;f1;");
        mSamplingOps.insert("texture2DProjLodEXT(1;vf4;f1;");
        mSamplingOps.insert("textureCubeLodEXT(1;vf4;f1;");
        mSamplingOps.insert("texture2DGradEXT(1;vf2;vf2;vf2;");
        mSamplingOps.insert("texture2DProjGradEXT(1;vf3;vf2;vf2;");
        mSamplingOps.insert("texture2DProjGradEXT(1;vf4;vf2;vf2;");
        mSamplingOps.insert("textureCubeGradEXT(1;vf3;vf3;vf3;");
    }
    
    // FIXME(mvujovic): We do not know if the execution time of built-in operations like sin, pow, etc.
    // can vary based on the value of the input arguments. If so, we should restrict those as well.
    void RestrictFragmentShaderTiming::enforceRestrictions(const TDependencyGraph& graph)
    {
        mNumErrors = 0;
    
        // FIXME(mvujovic): The dependency graph does not support user defined function calls right now,
        // so we generate errors for them.
        validateUserDefinedFunctionCallUsage(graph);
    
        // Starting from each sampler, traverse the dependency graph and generate an error each time we
        // hit a node where sampler dependent values are not allowed.
        for (auto samplerSymbol : graph.samplerSymbols())
        {
            clearVisited();
            samplerSymbol->traverse(this);
        }
    }
    
    void RestrictFragmentShaderTiming::validateUserDefinedFunctionCallUsage(const TDependencyGraph& graph)
    {
        for (const auto* functionCall : graph.userDefinedFunctionCalls())
        {
            beginError(functionCall->getIntermFunctionCall());
            mSink << "A call to a user defined function is not permitted.\n";
        }
    }
    
    void RestrictFragmentShaderTiming::beginError(const TIntermNode* node)
    {
        ++mNumErrors;
        mSink.prefix(EPrefixError);
        mSink.location(node->getLine());
    }
    
    bool RestrictFragmentShaderTiming::isSamplingOp(const TIntermAggregate* intermFunctionCall) const
    {
        return !intermFunctionCall->isUserDefined() &&
               mSamplingOps.find(intermFunctionCall->getName()) != mSamplingOps.end();
    }
    
    void RestrictFragmentShaderTiming::visitArgument(TGraphArgument* parameter)
    {
        // Texture cache access time might leak sensitive information.
        // Thus, we restrict sampler dependent values from affecting the coordinate or LOD bias of a
        // sampling operation.
        if (isSamplingOp(parameter->getIntermFunctionCall())) {
            switch (parameter->getArgumentNumber()) {
                case 1:
                    // Second argument (coord)
                    beginError(parameter->getIntermFunctionCall());
                    mSink << "An expression dependent on a sampler is not permitted to be the"
                          << " coordinate argument of a sampling operation.\n";
                    break;
                case 2:
                    // Third argument (bias)
                    beginError(parameter->getIntermFunctionCall());
                    mSink << "An expression dependent on a sampler is not permitted to be the"
                          << " bias argument of a sampling operation.\n";
                    break;
                default:
                    // First argument (sampler)
                    break;
            }
        }
    }
    
    void RestrictFragmentShaderTiming::visitSelection(TGraphSelection* selection)
    {
        beginError(selection->getIntermSelection());
        mSink << "An expression dependent on a sampler is not permitted in a conditional statement.\n";
    }
    
    void RestrictFragmentShaderTiming::visitLoop(TGraphLoop* loop)
    {
        beginError(loop->getIntermLoop());
        mSink << "An expression dependent on a sampler is not permitted in a loop condition.\n";
    }
    
    void RestrictFragmentShaderTiming::visitLogicalOp(TGraphLogicalOp* logicalOp)
    {
        beginError(logicalOp->getIntermLogicalOp());
        mSink << "An expression dependent on a sampler is not permitted on the left hand side of a logical "
              << logicalOp->getOpString()
              << " operator.\n";
    }