gfx/angle/src/compiler/timing/RestrictFragmentShaderTiming.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/angle/src/compiler/timing/RestrictFragmentShaderTiming.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,127 @@
     1.4 +//
     1.5 +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
     1.6 +// Use of this source code is governed by a BSD-style license that can be
     1.7 +// found in the LICENSE file.
     1.8 +//
     1.9 +
    1.10 +#include "compiler/InfoSink.h"
    1.11 +#include "compiler/ParseHelper.h"
    1.12 +#include "compiler/depgraph/DependencyGraphOutput.h"
    1.13 +#include "compiler/timing/RestrictFragmentShaderTiming.h"
    1.14 +
    1.15 +RestrictFragmentShaderTiming::RestrictFragmentShaderTiming(TInfoSinkBase& sink)
    1.16 +    : mSink(sink)
    1.17 +    , mNumErrors(0)
    1.18 +{
    1.19 +    // Sampling ops found only in fragment shaders.
    1.20 +    mSamplingOps.insert("texture2D(s21;vf2;f1;");
    1.21 +    mSamplingOps.insert("texture2DProj(s21;vf3;f1;");
    1.22 +    mSamplingOps.insert("texture2DProj(s21;vf4;f1;");
    1.23 +    mSamplingOps.insert("textureCube(sC1;vf3;f1;");
    1.24 +    // Sampling ops found in both vertex and fragment shaders.
    1.25 +    mSamplingOps.insert("texture2D(s21;vf2;");
    1.26 +    mSamplingOps.insert("texture2DProj(s21;vf3;");
    1.27 +    mSamplingOps.insert("texture2DProj(s21;vf4;");
    1.28 +    mSamplingOps.insert("textureCube(sC1;vf3;");
    1.29 +    // Sampling ops provided by OES_EGL_image_external.
    1.30 +    mSamplingOps.insert("texture2D(1;vf2;");
    1.31 +    mSamplingOps.insert("texture2DProj(1;vf3;");
    1.32 +    mSamplingOps.insert("texture2DProj(1;vf4;");
    1.33 +    // Sampling ops provided by ARB_texture_rectangle.
    1.34 +    mSamplingOps.insert("texture2DRect(1;vf2;");
    1.35 +    mSamplingOps.insert("texture2DRectProj(1;vf3;");
    1.36 +    mSamplingOps.insert("texture2DRectProj(1;vf4;");
    1.37 +}
    1.38 +
    1.39 +// FIXME(mvujovic): We do not know if the execution time of built-in operations like sin, pow, etc.
    1.40 +// can vary based on the value of the input arguments. If so, we should restrict those as well.
    1.41 +void RestrictFragmentShaderTiming::enforceRestrictions(const TDependencyGraph& graph)
    1.42 +{
    1.43 +    mNumErrors = 0;
    1.44 +
    1.45 +    // FIXME(mvujovic): The dependency graph does not support user defined function calls right now,
    1.46 +    // so we generate errors for them.
    1.47 +    validateUserDefinedFunctionCallUsage(graph);
    1.48 +
    1.49 +    // Starting from each sampler, traverse the dependency graph and generate an error each time we
    1.50 +    // hit a node where sampler dependent values are not allowed.
    1.51 +    for (TGraphSymbolVector::const_iterator iter = graph.beginSamplerSymbols();
    1.52 +         iter != graph.endSamplerSymbols();
    1.53 +         ++iter)
    1.54 +    {
    1.55 +        TGraphSymbol* samplerSymbol = *iter;
    1.56 +        clearVisited();
    1.57 +        samplerSymbol->traverse(this);
    1.58 +    }
    1.59 +}
    1.60 +
    1.61 +void RestrictFragmentShaderTiming::validateUserDefinedFunctionCallUsage(const TDependencyGraph& graph)
    1.62 +{
    1.63 +    for (TFunctionCallVector::const_iterator iter = graph.beginUserDefinedFunctionCalls();
    1.64 +         iter != graph.endUserDefinedFunctionCalls();
    1.65 +         ++iter)
    1.66 +    {
    1.67 +        TGraphFunctionCall* functionCall = *iter;
    1.68 +        beginError(functionCall->getIntermFunctionCall());
    1.69 +        mSink << "A call to a user defined function is not permitted.\n";
    1.70 +    }
    1.71 +}
    1.72 +
    1.73 +void RestrictFragmentShaderTiming::beginError(const TIntermNode* node)
    1.74 +{
    1.75 +    ++mNumErrors;
    1.76 +    mSink.prefix(EPrefixError);
    1.77 +    mSink.location(node->getLine());
    1.78 +}
    1.79 +
    1.80 +bool RestrictFragmentShaderTiming::isSamplingOp(const TIntermAggregate* intermFunctionCall) const
    1.81 +{
    1.82 +    return !intermFunctionCall->isUserDefined() &&
    1.83 +           mSamplingOps.find(intermFunctionCall->getName()) != mSamplingOps.end();
    1.84 +}
    1.85 +
    1.86 +void RestrictFragmentShaderTiming::visitArgument(TGraphArgument* parameter)
    1.87 +{
    1.88 +    // Texture cache access time might leak sensitive information.
    1.89 +    // Thus, we restrict sampler dependent values from affecting the coordinate or LOD bias of a
    1.90 +    // sampling operation.
    1.91 +    if (isSamplingOp(parameter->getIntermFunctionCall())) {
    1.92 +        switch (parameter->getArgumentNumber()) {
    1.93 +            case 1:
    1.94 +                // Second argument (coord)
    1.95 +                beginError(parameter->getIntermFunctionCall());
    1.96 +                mSink << "An expression dependent on a sampler is not permitted to be the"
    1.97 +                      << " coordinate argument of a sampling operation.\n";
    1.98 +                break;
    1.99 +            case 2:
   1.100 +                // Third argument (bias)
   1.101 +                beginError(parameter->getIntermFunctionCall());
   1.102 +                mSink << "An expression dependent on a sampler is not permitted to be the"
   1.103 +                      << " bias argument of a sampling operation.\n";
   1.104 +                break;
   1.105 +            default:
   1.106 +                // First argument (sampler)
   1.107 +                break;
   1.108 +        }
   1.109 +    }
   1.110 +}
   1.111 +
   1.112 +void RestrictFragmentShaderTiming::visitSelection(TGraphSelection* selection)
   1.113 +{
   1.114 +    beginError(selection->getIntermSelection());
   1.115 +    mSink << "An expression dependent on a sampler is not permitted in a conditional statement.\n";
   1.116 +}
   1.117 +
   1.118 +void RestrictFragmentShaderTiming::visitLoop(TGraphLoop* loop)
   1.119 +{
   1.120 +    beginError(loop->getIntermLoop());
   1.121 +    mSink << "An expression dependent on a sampler is not permitted in a loop condition.\n";
   1.122 +}
   1.123 +
   1.124 +void RestrictFragmentShaderTiming::visitLogicalOp(TGraphLogicalOp* logicalOp)
   1.125 +{
   1.126 +    beginError(logicalOp->getIntermLogicalOp());
   1.127 +    mSink << "An expression dependent on a sampler is not permitted on the left hand side of a logical "
   1.128 +          << logicalOp->getOpString()
   1.129 +          << " operator.\n";
   1.130 +}

mercurial