Line data Source code
1 : /*
2 : * Copyright (C) 2012 Apple Inc. All rights reserved.
3 : *
4 : * Redistribution and use in source and binary forms, with or without
5 : * modification, are permitted provided that the following conditions
6 : * are met:
7 : * 1. Redistributions of source code must retain the above copyright
8 : * notice, this list of conditions and the following disclaimer.
9 : * 2. Redistributions in binary form must reproduce the above copyright
10 : * notice, this list of conditions and the following disclaimer in the
11 : * documentation and/or other materials provided with the distribution.
12 : *
13 : * THIS SOFTWARE IS PROVIDED BY APPLE, INC. ``AS IS'' AND ANY
14 : * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 : * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE, INC. OR
17 : * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 : * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 : * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 : * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 : * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 : * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 : */
25 :
26 : #include "third_party/compiler/ArrayBoundsClamper.h"
27 :
28 : // The built-in 'clamp' instruction only accepts floats and returns a float. I
29 : // iterated a few times with our driver team who examined the output from our
30 : // compiler - they said the multiple casts generates more code than a single
31 : // function call. An inline ternary operator might have been better, but since
32 : // the index value might be an expression itself, we'd have to make temporary
33 : // variables to avoid evaluating the expression multiple times. And making
34 : // temporary variables was difficult because ANGLE would then need to make more
35 : // brutal changes to the expression tree.
36 :
37 : const char* kIntClampBegin = "// BEGIN: Generated code for array bounds clamping\n\n";
38 : const char* kIntClampEnd = "// END: Generated code for array bounds clamping\n\n";
39 : const char* kIntClampDefinition = "int webgl_int_clamp(int value, int minValue, int maxValue) { return ((value < minValue) ? minValue : ((value > maxValue) ? maxValue : value)); }\n\n";
40 :
41 : namespace sh
42 : {
43 :
44 : namespace
45 : {
46 :
47 0 : class ArrayBoundsClamperMarker : public TIntermTraverser {
48 : public:
49 0 : ArrayBoundsClamperMarker()
50 0 : : TIntermTraverser(true, false, false),
51 0 : mNeedsClamp(false)
52 : {
53 0 : }
54 :
55 0 : bool visitBinary(Visit visit, TIntermBinary *node) override
56 : {
57 0 : if (node->getOp() == EOpIndexIndirect)
58 : {
59 0 : TIntermTyped* left = node->getLeft();
60 0 : if (left->isArray() || left->isVector() || left->isMatrix())
61 : {
62 0 : node->setAddIndexClamp();
63 0 : mNeedsClamp = true;
64 : }
65 : }
66 0 : return true;
67 : }
68 :
69 0 : bool GetNeedsClamp() { return mNeedsClamp; }
70 :
71 : private:
72 : bool mNeedsClamp;
73 : };
74 :
75 : } // anonymous namespace
76 :
77 0 : ArrayBoundsClamper::ArrayBoundsClamper()
78 : : mClampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC)
79 0 : , mArrayBoundsClampDefinitionNeeded(false)
80 : {
81 0 : }
82 :
83 0 : void ArrayBoundsClamper::SetClampingStrategy(ShArrayIndexClampingStrategy clampingStrategy)
84 : {
85 0 : mClampingStrategy = clampingStrategy;
86 0 : }
87 :
88 0 : void ArrayBoundsClamper::MarkIndirectArrayBoundsForClamping(TIntermNode* root)
89 : {
90 0 : ASSERT(root);
91 :
92 0 : ArrayBoundsClamperMarker clamper;
93 0 : root->traverse(&clamper);
94 0 : if (clamper.GetNeedsClamp())
95 : {
96 0 : SetArrayBoundsClampDefinitionNeeded();
97 : }
98 0 : }
99 :
100 0 : void ArrayBoundsClamper::OutputClampingFunctionDefinition(TInfoSinkBase& out) const
101 : {
102 0 : if (!mArrayBoundsClampDefinitionNeeded)
103 : {
104 0 : return;
105 : }
106 0 : if (mClampingStrategy != SH_CLAMP_WITH_USER_DEFINED_INT_CLAMP_FUNCTION)
107 : {
108 0 : return;
109 : }
110 0 : out << kIntClampBegin << kIntClampDefinition << kIntClampEnd;
111 : }
112 :
113 : } // namespace sh
|