Add mediump and lowp precision emulation support for GLSL output
This implements the rounding as specified in WEBGL_debug_shader_precision
extension proposal for desktop GLSL and ESSL output. The bulk of the new
functionality is added in the form of a new EmulatePrecision AST
traverser, which inserts calls to the rounding routines angle_frm and
angle_frl in the appropriate places, and writes the rounding routines
themselves to the shader.
Compound assignments which are subject to emulation are transformed from
"x op= y" to "angle_compound_op_frm(x, y)", a call to a function which
does the appropriate rounding and places the result of the operation to
x.
The angle_ prefixed names should not clash with user-defined names if
name hashing is on. If name hashing is not on, the precision emulation
can only be used if the angle_ prefix is reserved for use by ANGLE.
To support the rounding routines in output, a new operator type is added
for internal helper function calls, which are not subject to name
hashing.
In ESSL output, all variables are forced to highp when precision
emulation is on to ensure consistency with how precision emulation
performs on desktop.
Comprehensive tests for the added code generation are included.
BUG=angle:787
Change-Id: I0d0ad9327888f803a32e79b64b08763c654c913b
Reviewed-on: https://chromium-review.googlesource.com/229631
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Tested-by: Olli Etuaho <oetuaho@nvidia.com>
diff --git a/src/compiler/translator/EmulatePrecision.h b/src/compiler/translator/EmulatePrecision.h
new file mode 100644
index 0000000..4b4c5b9
--- /dev/null
+++ b/src/compiler/translator/EmulatePrecision.h
@@ -0,0 +1,76 @@
+//
+// Copyright (c) 2002-2014 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.
+//
+
+#ifndef COMPILER_TRANSLATOR_EMULATE_PRECISION_H_
+#define COMPILER_TRANSLATOR_EMULATE_PRECISION_H_
+
+#include "common/angleutils.h"
+#include "compiler/translator/InfoSink.h"
+#include "compiler/translator/IntermNode.h"
+#include "GLSLANG/ShaderLang.h"
+
+// This class gathers all compound assignments from the AST and can then write
+// the functions required for their precision emulation. This way there is no
+// need to write a huge number of variations of the emulated compound assignment
+// to every translated shader with emulation enabled.
+
+class EmulatePrecision : public TIntermTraverser
+{
+ public:
+ EmulatePrecision();
+
+ virtual void visitSymbol(TIntermSymbol *node);
+ virtual bool visitBinary(Visit visit, TIntermBinary *node);
+ virtual bool visitUnary(Visit visit, TIntermUnary *node);
+ virtual bool visitAggregate(Visit visit, TIntermAggregate *node);
+
+ void writeEmulationHelpers(TInfoSinkBase& sink, ShShaderOutput outputLanguage);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(EmulatePrecision);
+
+ struct TypePair
+ {
+ TypePair(const char *l, const char *r)
+ : lType(l), rType(r) { }
+
+ const char *lType;
+ const char *rType;
+ };
+
+ struct TypePairComparator
+ {
+ bool operator() (const TypePair& l, const TypePair& r) const
+ {
+ if (l.lType == r.lType)
+ return l.rType < r.rType;
+ return l.lType < r.lType;
+ }
+ };
+
+ typedef std::set<TypePair, TypePairComparator> EmulationSet;
+ EmulationSet mEmulateCompoundAdd;
+ EmulationSet mEmulateCompoundSub;
+ EmulationSet mEmulateCompoundMul;
+ EmulationSet mEmulateCompoundDiv;
+
+ // Stack of function call parameter iterators
+ std::vector<TIntermSequence::const_iterator> mSeqIterStack;
+
+ bool mDeclaringVariables;
+ bool mInLValue;
+ bool mInFunctionCallOutParameter;
+
+ struct TStringComparator
+ {
+ bool operator() (const TString& a, const TString& b) const { return a.compare(b) < 0; }
+ };
+
+ // Map from function names to their parameter sequences
+ std::map<TString, TIntermSequence*, TStringComparator> mFunctionMap;
+};
+
+#endif // COMPILER_TRANSLATOR_EMULATE_PRECISION_H_