diff options
Diffstat (limited to 'gfx/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.cpp')
-rw-r--r-- | gfx/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.cpp | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/gfx/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.cpp b/gfx/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.cpp new file mode 100644 index 000000000..790974a2b --- /dev/null +++ b/gfx/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.cpp @@ -0,0 +1,130 @@ +// +// 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"; +} |