Wed, 31 Dec 2014 07:16:47 +0100
Revert simplistic fix pending revisit of Mozilla integration attempt.
1 //
2 // Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
7 #include "compiler/InfoSink.h"
8 #include "compiler/ParseHelper.h"
9 #include "compiler/depgraph/DependencyGraphOutput.h"
10 #include "compiler/timing/RestrictFragmentShaderTiming.h"
12 RestrictFragmentShaderTiming::RestrictFragmentShaderTiming(TInfoSinkBase& sink)
13 : mSink(sink)
14 , mNumErrors(0)
15 {
16 // Sampling ops found only in fragment shaders.
17 mSamplingOps.insert("texture2D(s21;vf2;f1;");
18 mSamplingOps.insert("texture2DProj(s21;vf3;f1;");
19 mSamplingOps.insert("texture2DProj(s21;vf4;f1;");
20 mSamplingOps.insert("textureCube(sC1;vf3;f1;");
21 // Sampling ops found in both vertex and fragment shaders.
22 mSamplingOps.insert("texture2D(s21;vf2;");
23 mSamplingOps.insert("texture2DProj(s21;vf3;");
24 mSamplingOps.insert("texture2DProj(s21;vf4;");
25 mSamplingOps.insert("textureCube(sC1;vf3;");
26 // Sampling ops provided by OES_EGL_image_external.
27 mSamplingOps.insert("texture2D(1;vf2;");
28 mSamplingOps.insert("texture2DProj(1;vf3;");
29 mSamplingOps.insert("texture2DProj(1;vf4;");
30 // Sampling ops provided by ARB_texture_rectangle.
31 mSamplingOps.insert("texture2DRect(1;vf2;");
32 mSamplingOps.insert("texture2DRectProj(1;vf3;");
33 mSamplingOps.insert("texture2DRectProj(1;vf4;");
34 }
36 // FIXME(mvujovic): We do not know if the execution time of built-in operations like sin, pow, etc.
37 // can vary based on the value of the input arguments. If so, we should restrict those as well.
38 void RestrictFragmentShaderTiming::enforceRestrictions(const TDependencyGraph& graph)
39 {
40 mNumErrors = 0;
42 // FIXME(mvujovic): The dependency graph does not support user defined function calls right now,
43 // so we generate errors for them.
44 validateUserDefinedFunctionCallUsage(graph);
46 // Starting from each sampler, traverse the dependency graph and generate an error each time we
47 // hit a node where sampler dependent values are not allowed.
48 for (TGraphSymbolVector::const_iterator iter = graph.beginSamplerSymbols();
49 iter != graph.endSamplerSymbols();
50 ++iter)
51 {
52 TGraphSymbol* samplerSymbol = *iter;
53 clearVisited();
54 samplerSymbol->traverse(this);
55 }
56 }
58 void RestrictFragmentShaderTiming::validateUserDefinedFunctionCallUsage(const TDependencyGraph& graph)
59 {
60 for (TFunctionCallVector::const_iterator iter = graph.beginUserDefinedFunctionCalls();
61 iter != graph.endUserDefinedFunctionCalls();
62 ++iter)
63 {
64 TGraphFunctionCall* functionCall = *iter;
65 beginError(functionCall->getIntermFunctionCall());
66 mSink << "A call to a user defined function is not permitted.\n";
67 }
68 }
70 void RestrictFragmentShaderTiming::beginError(const TIntermNode* node)
71 {
72 ++mNumErrors;
73 mSink.prefix(EPrefixError);
74 mSink.location(node->getLine());
75 }
77 bool RestrictFragmentShaderTiming::isSamplingOp(const TIntermAggregate* intermFunctionCall) const
78 {
79 return !intermFunctionCall->isUserDefined() &&
80 mSamplingOps.find(intermFunctionCall->getName()) != mSamplingOps.end();
81 }
83 void RestrictFragmentShaderTiming::visitArgument(TGraphArgument* parameter)
84 {
85 // Texture cache access time might leak sensitive information.
86 // Thus, we restrict sampler dependent values from affecting the coordinate or LOD bias of a
87 // sampling operation.
88 if (isSamplingOp(parameter->getIntermFunctionCall())) {
89 switch (parameter->getArgumentNumber()) {
90 case 1:
91 // Second argument (coord)
92 beginError(parameter->getIntermFunctionCall());
93 mSink << "An expression dependent on a sampler is not permitted to be the"
94 << " coordinate argument of a sampling operation.\n";
95 break;
96 case 2:
97 // Third argument (bias)
98 beginError(parameter->getIntermFunctionCall());
99 mSink << "An expression dependent on a sampler is not permitted to be the"
100 << " bias argument of a sampling operation.\n";
101 break;
102 default:
103 // First argument (sampler)
104 break;
105 }
106 }
107 }
109 void RestrictFragmentShaderTiming::visitSelection(TGraphSelection* selection)
110 {
111 beginError(selection->getIntermSelection());
112 mSink << "An expression dependent on a sampler is not permitted in a conditional statement.\n";
113 }
115 void RestrictFragmentShaderTiming::visitLoop(TGraphLoop* loop)
116 {
117 beginError(loop->getIntermLoop());
118 mSink << "An expression dependent on a sampler is not permitted in a loop condition.\n";
119 }
121 void RestrictFragmentShaderTiming::visitLogicalOp(TGraphLogicalOp* logicalOp)
122 {
123 beginError(logicalOp->getIntermLogicalOp());
124 mSink << "An expression dependent on a sampler is not permitted on the left hand side of a logical "
125 << logicalOp->getOpString()
126 << " operator.\n";
127 }