Hash :
da9fb093
Author :
Date :
2016-12-09T17:32:29
Work around atan(y, x) bug on NVIDIA atan(y, x) is not always returning expected results on NVIDIA OpenGL drivers between versions 367 and 375. Work around this by emulating atan(y, x) using the regular atan(x) function. A fix to the driver is expected in a future release. It is most convenient to implement the vector atan(y, x) functions by using the scalar atan(y, x) function. Support for simple dependencies between emulated functions is added to BuiltInFunctionEmulator. In the current implementation one function is allowed to have at most one other function as its dependency. BUG=chromium:672380 TEST=angle_end2end_tests Change-Id: I9eba8b0b7979c7c7eaed353b264932e41830beb1 Reviewed-on: https://chromium-review.googlesource.com/419016 Commit-Queue: Olli Etuaho <oetuaho@nvidia.com> Reviewed-by: Jamie Madill <jmadill@chromium.org>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
//
// Copyright (c) 2011 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_BUILTINFUNCTIONEMULATOR_H_
#define COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_
#include "compiler/translator/InfoSink.h"
#include "compiler/translator/IntermNode.h"
namespace sh
{
//
// This class decides which built-in functions need to be replaced with the emulated ones. It can be
// used to work around driver bugs or implement functions that are not natively implemented on a
// specific platform.
//
class BuiltInFunctionEmulator
{
public:
BuiltInFunctionEmulator();
void MarkBuiltInFunctionsForEmulation(TIntermNode *root);
void Cleanup();
// "name(" becomes "webgl_name_emu(".
static TString GetEmulatedFunctionName(const TString &name);
bool IsOutputEmpty() const;
// Output function emulation definition. This should be before any other shader source.
void OutputEmulatedFunctions(TInfoSinkBase &out) const;
class FunctionId
{
public:
FunctionId();
FunctionId(TOperator op, const TType *param);
FunctionId(TOperator op, const TType *param1, const TType *param2);
FunctionId(TOperator op, const TType *param1, const TType *param2, const TType *param3);
FunctionId(const FunctionId &) = default;
FunctionId &operator=(const FunctionId &) = default;
bool operator==(const FunctionId &other) const;
bool operator<(const FunctionId &other) const;
FunctionId getCopy() const;
private:
TOperator mOp;
// The memory that these TType objects use is freed by PoolAllocator. The
// BuiltInFunctionEmulator's lifetime can extend until after the memory pool is freed, but
// that's not an issue since this class never destructs these objects.
const TType *mParam1;
const TType *mParam2;
const TType *mParam3;
};
// Add functions that need to be emulated.
FunctionId addEmulatedFunction(TOperator op,
const TType *param,
const char *emulatedFunctionDefinition);
FunctionId addEmulatedFunction(TOperator op,
const TType *param1,
const TType *param2,
const char *emulatedFunctionDefinition);
FunctionId addEmulatedFunction(TOperator op,
const TType *param1,
const TType *param2,
const TType *param3,
const char *emulatedFunctionDefinition);
FunctionId addEmulatedFunctionWithDependency(FunctionId dependency,
TOperator op,
const TType *param1,
const TType *param2,
const char *emulatedFunctionDefinition);
private:
class BuiltInFunctionEmulationMarker;
// Records that a function is called by the shader and might need to be emulated. If the
// function is not in mEmulatedFunctions, this becomes a no-op. Returns true if the function
// call needs to be replaced with an emulated one.
bool SetFunctionCalled(TOperator op, const TType ¶m);
bool SetFunctionCalled(TOperator op, const TType ¶m1, const TType ¶m2);
bool SetFunctionCalled(TOperator op,
const TType ¶m1,
const TType ¶m2,
const TType ¶m3);
bool SetFunctionCalled(const FunctionId &functionId);
// Map from function id to emulated function definition
std::map<FunctionId, std::string> mEmulatedFunctions;
// Map from dependent functions to their dependencies. This structure allows each function to
// have at most one dependency.
std::map<FunctionId, FunctionId> mFunctionDependencies;
// Called function ids
std::vector<FunctionId> mFunctions;
};
} // namespace sh
#endif // COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_