Commit f420c424 by zmo@google.com

Add/remove more functions to use shims.

Remove normalize and add cos instead to avoid a crash in Mac with ATI cards (angle bug 193, 202). Also add atan and mod as it's also buggy on Mac/Win with NVIDIA cards. Also, trying to minimize emulated functions by adding masks for fragment/vertex shaders. ANGLEBUG=196 Review URL: http://codereview.appspot.com/4992047 git-svn-id: https://angleproject.googlecode.com/svn/trunk@748 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent 2598ffff
#define MAJOR_VERSION 0 #define MAJOR_VERSION 0
#define MINOR_VERSION 0 #define MINOR_VERSION 0
#define BUILD_VERSION 0 #define BUILD_VERSION 0
#define BUILD_REVISION 747 #define BUILD_REVISION 748
#define STRINGIFY(x) #x #define STRINGIFY(x) #x
#define MACRO_STRINGIFY(x) STRINGIFY(x) #define MACRO_STRINGIFY(x) STRINGIFY(x)
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
#ifndef COMPILIER_BUILT_IN_FUNCTION_EMULATOR_H_ #ifndef COMPILIER_BUILT_IN_FUNCTION_EMULATOR_H_
#define COMPILIER_BUILT_IN_FUNCTION_EMULATOR_H_ #define COMPILIER_BUILT_IN_FUNCTION_EMULATOR_H_
#include "GLSLANG/ShaderLang.h"
#include "compiler/InfoSink.h" #include "compiler/InfoSink.h"
#include "compiler/intermediate.h" #include "compiler/intermediate.h"
...@@ -15,11 +17,16 @@ ...@@ -15,11 +17,16 @@
// emulated in certain os/drivers, assuming they are no more than 32. // emulated in certain os/drivers, assuming they are no more than 32.
// //
enum TBuiltInFunctionGroup { enum TBuiltInFunctionGroup {
TFunctionGroupNormalize = 1 << 0, TFunctionGroupAbs = 1 << 0, // NVIDIA Win/Mac
TFunctionGroupAbs = 1 << 1, TFunctionGroupAtan = 1 << 1, // NVIDIA Win/Mac
TFunctionGroupSign = 1 << 2, TFunctionGroupCos = 1 << 2, // ATI Mac
TFunctionGroupAll = TFunctionGroupMod = 1 << 3, // NVIDIA Win/Mac
TFunctionGroupNormalize | TFunctionGroupAbs | TFunctionGroupSign TFunctionGroupSign = 1 << 4, // NVIDIA Win/Mac
TFunctionGroupAll = TFunctionGroupAbs |
TFunctionGroupAtan |
TFunctionGroupCos |
TFunctionGroupMod |
TFunctionGroupSign
}; };
// //
...@@ -29,7 +36,7 @@ enum TBuiltInFunctionGroup { ...@@ -29,7 +36,7 @@ enum TBuiltInFunctionGroup {
// //
class BuiltInFunctionEmulator { class BuiltInFunctionEmulator {
public: public:
BuiltInFunctionEmulator(); BuiltInFunctionEmulator(ShShaderType shaderType);
// functionGroupMask is a bitmap of TBuiltInFunctionGroup. // functionGroupMask is a bitmap of TBuiltInFunctionGroup.
// We only emulate functions that are marked by this mask and are actually // We only emulate functions that are marked by this mask and are actually
...@@ -42,10 +49,9 @@ public: ...@@ -42,10 +49,9 @@ public:
// becomes an no-op. // becomes an no-op.
// Returns true if the function call needs to be replaced with an emulated // Returns true if the function call needs to be replaced with an emulated
// one. // one.
// TODO(zmo): for now, an operator and a return type is enough to identify bool SetFunctionCalled(TOperator op, const TType& param);
// the function we want to emulate. Should make this more flexible to bool SetFunctionCalled(
// handle any functions. TOperator op, const TType& param1, const TType& param2);
bool SetFunctionCalled(TOperator op, const TType& returnType);
// Output function emulation definition. This should be before any other // Output function emulation definition. This should be before any other
// shader source. // shader source.
...@@ -61,14 +67,30 @@ private: ...@@ -61,14 +67,30 @@ private:
// Built-in functions. // Built-in functions.
// //
enum TBuiltInFunction { enum TBuiltInFunction {
TFunctionNormalize1 = 0, // float normalize(float); TFunctionAbs1 = 0, // float abs(float);
TFunctionNormalize2, // vec2 normalize(vec2);
TFunctionNormalize3, // vec3 normalize(vec3);
TFunctionNormalize4, // fec4 normalize(vec4);
TFunctionAbs1, // float abs(float);
TFunctionAbs2, // vec2 abs(vec2); TFunctionAbs2, // vec2 abs(vec2);
TFunctionAbs3, // vec3 abs(vec3); TFunctionAbs3, // vec3 abs(vec3);
TFunctionAbs4, // vec4 abs(vec4); TFunctionAbs4, // vec4 abs(vec4);
TFunctionAtan1, // float atan(float);
TFunctionAtan2, // vec2 atan(vec2);
TFunctionAtan3, // vec3 atan(vec3);
TFunctionAtan4, // vec4 atan(vec4);
TFunctionAtan1_1, // float atan(float, float);
TFunctionAtan2_2, // vec2 atan(vec2, vec2);
TFunctionAtan3_3, // vec3 atan(vec3, vec2);
TFunctionAtan4_4, // vec4 atan(vec4, vec2);
TFunctionCos1, // float cos(float);
TFunctionCos2, // vec2 cos(vec2);
TFunctionCos3, // vec3 cos(vec3);
TFunctionCos4, // vec4 cos(vec4);
TFunctionMod1_1, // float mod(float, float);
TFunctionMod2_2, // vec2 mod(vec2, vec2);
TFunctionMod3_3, // vec3 mod(vec3, vec3);
TFunctionMod4_4, // vec4 mod(vec4, vec4);
TFunctionSign1, // float sign(float); TFunctionSign1, // float sign(float);
TFunctionSign2, // vec2 sign(vec2); TFunctionSign2, // vec2 sign(vec2);
TFunctionSign3, // vec3 sign(vec3); TFunctionSign3, // vec3 sign(vec3);
...@@ -76,11 +98,16 @@ private: ...@@ -76,11 +98,16 @@ private:
TFunctionUnknown TFunctionUnknown
}; };
// Same TODO as SetFunctionCalled. TBuiltInFunction IdentifyFunction(TOperator op, const TType& param);
TBuiltInFunction IdentifyFunction(TOperator op, const TType& returnType); TBuiltInFunction IdentifyFunction(
TOperator op, const TType& param1, const TType& param2);
bool SetFunctionCalled(TBuiltInFunction function);
TVector<TBuiltInFunction> mFunctions; TVector<TBuiltInFunction> mFunctions;
unsigned int mFunctionGroupMask; // a bitmap of TBuiltInFunctionGroup. unsigned int mFunctionGroupMask; // a bitmap of TBuiltInFunctionGroup.
const bool* mFunctionMask; // a boolean flag for each function.
}; };
#endif // COMPILIER_BUILT_IN_FUNCTION_EMULATOR_H_ #endif // COMPILIER_BUILT_IN_FUNCTION_EMULATOR_H_
...@@ -88,7 +88,8 @@ TShHandleBase::~TShHandleBase() { ...@@ -88,7 +88,8 @@ TShHandleBase::~TShHandleBase() {
TCompiler::TCompiler(ShShaderType type, ShShaderSpec spec) TCompiler::TCompiler(ShShaderType type, ShShaderSpec spec)
: shaderType(type), : shaderType(type),
shaderSpec(spec) shaderSpec(spec),
builtInFunctionEmulator(type)
{ {
} }
......
...@@ -436,6 +436,8 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate* node) ...@@ -436,6 +436,8 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate* node)
{ {
bool visitChildren = true; bool visitChildren = true;
TInfoSinkBase& out = objSink(); TInfoSinkBase& out = objSink();
TString preString;
bool delayedWrite = false;
switch (node->getOp()) switch (node->getOp())
{ {
case EOpSequence: { case EOpSequence: {
...@@ -582,34 +584,38 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate* node) ...@@ -582,34 +584,38 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate* node)
} }
break; break;
case EOpLessThan: writeTriplet(visit, "lessThan(", ", ", ")"); break; case EOpLessThan: preString = "lessThan("; delayedWrite = true; break;
case EOpGreaterThan: writeTriplet(visit, "greaterThan(", ", ", ")"); break; case EOpGreaterThan: preString = "greaterThan("; delayedWrite = true; break;
case EOpLessThanEqual: writeTriplet(visit, "lessThanEqual(", ", ", ")"); break; case EOpLessThanEqual: preString = "lessThanEqual("; delayedWrite = true; break;
case EOpGreaterThanEqual: writeTriplet(visit, "greaterThanEqual(", ", ", ")"); break; case EOpGreaterThanEqual: preString = "greaterThanEqual("; delayedWrite = true; break;
case EOpVectorEqual: writeTriplet(visit, "equal(", ", ", ")"); break; case EOpVectorEqual: preString = "equal("; delayedWrite = true; break;
case EOpVectorNotEqual: writeTriplet(visit, "notEqual(", ", ", ")"); break; case EOpVectorNotEqual: preString = "notEqual("; delayedWrite = true; break;
case EOpComma: writeTriplet(visit, NULL, ", ", NULL); break; case EOpComma: writeTriplet(visit, NULL, ", ", NULL); break;
case EOpMod: writeTriplet(visit, "mod(", ", ", ")"); break; case EOpMod: preString = "mod("; delayedWrite = true; break;
case EOpPow: writeTriplet(visit, "pow(", ", ", ")"); break; case EOpPow: preString = "pow("; delayedWrite = true; break;
case EOpAtan: writeTriplet(visit, "atan(", ", ", ")"); break; case EOpAtan: preString = "atan("; delayedWrite = true; break;
case EOpMin: writeTriplet(visit, "min(", ", ", ")"); break; case EOpMin: preString = "min("; delayedWrite = true; break;
case EOpMax: writeTriplet(visit, "max(", ", ", ")"); break; case EOpMax: preString = "max("; delayedWrite = true; break;
case EOpClamp: writeTriplet(visit, "clamp(", ", ", ")"); break; case EOpClamp: preString = "clamp("; delayedWrite = true; break;
case EOpMix: writeTriplet(visit, "mix(", ", ", ")"); break; case EOpMix: preString = "mix("; delayedWrite = true; break;
case EOpStep: writeTriplet(visit, "step(", ", ", ")"); break; case EOpStep: preString = "step("; delayedWrite = true; break;
case EOpSmoothStep: writeTriplet(visit, "smoothstep(", ", ", ")"); break; case EOpSmoothStep: preString = "smoothstep("; delayedWrite = true; break;
case EOpDistance: writeTriplet(visit, "distance(", ", ", ")"); break; case EOpDistance: preString = "distance("; delayedWrite = true; break;
case EOpDot: writeTriplet(visit, "dot(", ", ", ")"); break; case EOpDot: preString = "dot("; delayedWrite = true; break;
case EOpCross: writeTriplet(visit, "cross(", ", ", ")"); break; case EOpCross: preString = "cross("; delayedWrite = true; break;
case EOpFaceForward: writeTriplet(visit, "faceforward(", ", ", ")"); break; case EOpFaceForward: preString = "faceforward("; delayedWrite = true; break;
case EOpReflect: writeTriplet(visit, "reflect(", ", ", ")"); break; case EOpReflect: preString = "reflect("; delayedWrite = true; break;
case EOpRefract: writeTriplet(visit, "refract(", ", ", ")"); break; case EOpRefract: preString = "refract("; delayedWrite = true; break;
case EOpMul: writeTriplet(visit, "matrixCompMult(", ", ", ")"); break; case EOpMul: preString = "matrixCompMult("; delayedWrite = true; break;
default: UNREACHABLE(); break; default: UNREACHABLE(); break;
} }
if (delayedWrite && visit == PreVisit && node->getUseEmulatedFunction())
preString = BuiltInFunctionEmulator::GetEmulatedFunctionName(preString);
if (delayedWrite)
writeTriplet(visit, preString.c_str(), ", ", ")");
return visitChildren; return visitChildren;
} }
......
...@@ -425,7 +425,10 @@ public: ...@@ -425,7 +425,10 @@ public:
protected: protected:
TIntermTyped* operand; TIntermTyped* operand;
bool useEmulatedFunction; // if set to true, replace the function call by an emulated one.
// If set to true, replace the built-in function call with an emulated one
// to work around driver bugs.
bool useEmulatedFunction;
}; };
typedef TVector<TIntermNode*> TIntermSequence; typedef TVector<TIntermNode*> TIntermSequence;
...@@ -436,8 +439,8 @@ typedef TMap<TString, TString> TPragmaTable; ...@@ -436,8 +439,8 @@ typedef TMap<TString, TString> TPragmaTable;
// //
class TIntermAggregate : public TIntermOperator { class TIntermAggregate : public TIntermOperator {
public: public:
TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), pragmaTable(0), endLine(0) { } TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), pragmaTable(0), endLine(0), useEmulatedFunction(false) { }
TIntermAggregate(TOperator o) : TIntermOperator(o), pragmaTable(0) { } TIntermAggregate(TOperator o) : TIntermOperator(o), pragmaTable(0), useEmulatedFunction(false) { }
~TIntermAggregate() { delete pragmaTable; } ~TIntermAggregate() { delete pragmaTable; }
virtual TIntermAggregate* getAsAggregate() { return this; } virtual TIntermAggregate* getAsAggregate() { return this; }
...@@ -460,6 +463,9 @@ public: ...@@ -460,6 +463,9 @@ public:
void setEndLine(TSourceLoc line) { endLine = line; } void setEndLine(TSourceLoc line) { endLine = line; }
TSourceLoc getEndLine() const { return endLine; } TSourceLoc getEndLine() const { return endLine; }
void setUseEmulatedFunction() { useEmulatedFunction = true; }
bool getUseEmulatedFunction() { return useEmulatedFunction; }
protected: protected:
TIntermAggregate(const TIntermAggregate&); // disallow copy constructor TIntermAggregate(const TIntermAggregate&); // disallow copy constructor
TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator
...@@ -471,6 +477,10 @@ protected: ...@@ -471,6 +477,10 @@ protected:
bool debug; bool debug;
TPragmaTable *pragmaTable; TPragmaTable *pragmaTable;
TSourceLoc endLine; TSourceLoc endLine;
// If set to true, replace the built-in function call with an emulated one
// to work around driver bugs.
bool useEmulatedFunction;
}; };
// //
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment