1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/angle/angle-faceforward-emu.patch Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,314 @@ 1.4 +From: Jeff Gilbert <jgilbert@mozilla.com> 1.5 +Bug 771406 - Add emulation for GLSL faceforward() to ANGLE - r=bjacob 1.6 + 1.7 +diff --git a/gfx/angle/src/compiler/BuiltInFunctionEmulator.cpp b/gfx/angle/src/compiler/BuiltInFunctionEmulator.cpp 1.8 +--- a/gfx/angle/src/compiler/BuiltInFunctionEmulator.cpp 1.9 ++++ b/gfx/angle/src/compiler/BuiltInFunctionEmulator.cpp 1.10 +@@ -26,16 +26,22 @@ const char* kFunctionEmulationVertexSour 1.11 + "#error no emulation for distance(vec3, vec3)", 1.12 + "#error no emulation for distance(vec4, vec4)", 1.13 + 1.14 + "#define webgl_dot_emu(x, y) ((x) * (y))", 1.15 + "#error no emulation for dot(vec2, vec2)", 1.16 + "#error no emulation for dot(vec3, vec3)", 1.17 + "#error no emulation for dot(vec4, vec4)", 1.18 + 1.19 ++ // |faceforward(N, I, Nref)| is |dot(NRef, I) < 0 ? N : -N| 1.20 ++ "#define webgl_faceforward_emu(N, I, Nref) (((Nref) * (I) < 0.0) ? (N) : -(N))", 1.21 ++ "#error no emulation for faceforward(vec2, vec2, vec2)", 1.22 ++ "#error no emulation for faceforward(vec3, vec3, vec3)", 1.23 ++ "#error no emulation for faceforward(vec4, vec4, vec4)", 1.24 ++ 1.25 + "#define webgl_length_emu(x) ((x) >= 0.0 ? (x) : -(x))", 1.26 + "#error no emulation for length(vec2)", 1.27 + "#error no emulation for length(vec3)", 1.28 + "#error no emulation for length(vec4)", 1.29 + 1.30 + "#define webgl_normalize_emu(x) ((x) == 0.0 ? 0.0 : ((x) > 0.0 ? 1.0 : -1.0))", 1.31 + "#error no emulation for normalize(vec2)", 1.32 + "#error no emulation for normalize(vec3)", 1.33 +@@ -58,16 +64,22 @@ const char* kFunctionEmulationFragmentSo 1.34 + "#error no emulation for distance(vec3, vec3)", 1.35 + "#error no emulation for distance(vec4, vec4)", 1.36 + 1.37 + "#define webgl_dot_emu(x, y) ((x) * (y))", 1.38 + "#error no emulation for dot(vec2, vec2)", 1.39 + "#error no emulation for dot(vec3, vec3)", 1.40 + "#error no emulation for dot(vec4, vec4)", 1.41 + 1.42 ++ // |faceforward(N, I, Nref)| is |dot(NRef, I) < 0 ? N : -N| 1.43 ++ "#define webgl_faceforward_emu(N, I, Nref) (((Nref) * (I) < 0.0) ? (N) : -(N))", 1.44 ++ "#error no emulation for faceforward(vec2, vec2, vec2)", 1.45 ++ "#error no emulation for faceforward(vec3, vec3, vec3)", 1.46 ++ "#error no emulation for faceforward(vec4, vec4, vec4)", 1.47 ++ 1.48 + "#define webgl_length_emu(x) ((x) >= 0.0 ? (x) : -(x))", 1.49 + "#error no emulation for length(vec2)", 1.50 + "#error no emulation for length(vec3)", 1.51 + "#error no emulation for length(vec4)", 1.52 + 1.53 + "#define webgl_normalize_emu(x) ((x) == 0.0 ? 0.0 : ((x) > 0.0 ? 1.0 : -1.0))", 1.54 + "#error no emulation for normalize(vec2)", 1.55 + "#error no emulation for normalize(vec3)", 1.56 +@@ -89,16 +101,20 @@ const bool kFunctionEmulationVertexMask[ 1.57 + true, // TFunctionDistance1_1 1.58 + false, // TFunctionDistance2_2 1.59 + false, // TFunctionDistance3_3 1.60 + false, // TFunctionDistance4_4 1.61 + true, // TFunctionDot1_1 1.62 + false, // TFunctionDot2_2 1.63 + false, // TFunctionDot3_3 1.64 + false, // TFunctionDot4_4 1.65 ++ true, // TFunctionFaceForward1_1_1 1.66 ++ false, // TFunctionFaceForward2_2_2 1.67 ++ false, // TFunctionFaceForward3_3_3 1.68 ++ false, // TFunctionFaceForward4_4_4 1.69 + true, // TFunctionLength1 1.70 + false, // TFunctionLength2 1.71 + false, // TFunctionLength3 1.72 + false, // TFunctionLength4 1.73 + true, // TFunctionNormalize1 1.74 + false, // TFunctionNormalize2 1.75 + false, // TFunctionNormalize3 1.76 + false, // TFunctionNormalize4 1.77 +@@ -115,16 +131,20 @@ const bool kFunctionEmulationVertexMask[ 1.78 + false, // TFunctionDistance1_1 1.79 + false, // TFunctionDistance2_2 1.80 + false, // TFunctionDistance3_3 1.81 + false, // TFunctionDistance4_4 1.82 + false, // TFunctionDot1_1 1.83 + false, // TFunctionDot2_2 1.84 + false, // TFunctionDot3_3 1.85 + false, // TFunctionDot4_4 1.86 ++ false, // TFunctionFaceForward1_1_1 1.87 ++ false, // TFunctionFaceForward2_2_2 1.88 ++ false, // TFunctionFaceForward3_3_3 1.89 ++ false, // TFunctionFaceForward4_4_4 1.90 + false, // TFunctionLength1 1.91 + false, // TFunctionLength2 1.92 + false, // TFunctionLength3 1.93 + false, // TFunctionLength4 1.94 + false, // TFunctionNormalize1 1.95 + false, // TFunctionNormalize2 1.96 + false, // TFunctionNormalize3 1.97 + false, // TFunctionNormalize4 1.98 +@@ -146,16 +166,20 @@ const bool kFunctionEmulationFragmentMas 1.99 + true, // TFunctionDistance1_1 1.100 + false, // TFunctionDistance2_2 1.101 + false, // TFunctionDistance3_3 1.102 + false, // TFunctionDistance4_4 1.103 + true, // TFunctionDot1_1 1.104 + false, // TFunctionDot2_2 1.105 + false, // TFunctionDot3_3 1.106 + false, // TFunctionDot4_4 1.107 ++ true, // TFunctionFaceForward1_1_1 1.108 ++ false, // TFunctionFaceForward2_2_2 1.109 ++ false, // TFunctionFaceForward3_3_3 1.110 ++ false, // TFunctionFaceForward4_4_4 1.111 + true, // TFunctionLength1 1.112 + false, // TFunctionLength2 1.113 + false, // TFunctionLength3 1.114 + false, // TFunctionLength4 1.115 + true, // TFunctionNormalize1 1.116 + false, // TFunctionNormalize2 1.117 + false, // TFunctionNormalize3 1.118 + false, // TFunctionNormalize4 1.119 +@@ -172,16 +196,20 @@ const bool kFunctionEmulationFragmentMas 1.120 + false, // TFunctionDistance1_1 1.121 + false, // TFunctionDistance2_2 1.122 + false, // TFunctionDistance3_3 1.123 + false, // TFunctionDistance4_4 1.124 + false, // TFunctionDot1_1 1.125 + false, // TFunctionDot2_2 1.126 + false, // TFunctionDot3_3 1.127 + false, // TFunctionDot4_4 1.128 ++ false, // TFunctionFaceForward1_1_1 1.129 ++ false, // TFunctionFaceForward2_2_2 1.130 ++ false, // TFunctionFaceForward3_3_3 1.131 ++ false, // TFunctionFaceForward4_4_4 1.132 + false, // TFunctionLength1 1.133 + false, // TFunctionLength2 1.134 + false, // TFunctionLength3 1.135 + false, // TFunctionLength4 1.136 + false, // TFunctionNormalize1 1.137 + false, // TFunctionNormalize2 1.138 + false, // TFunctionNormalize3 1.139 + false, // TFunctionNormalize4 1.140 +@@ -239,25 +267,37 @@ public: 1.141 + case EOpReflect: 1.142 + case EOpRefract: 1.143 + case EOpMul: 1.144 + break; 1.145 + default: 1.146 + return true; 1.147 + }; 1.148 + const TIntermSequence& sequence = node->getSequence(); 1.149 +- // Right now we only handle built-in functions with two parameters. 1.150 +- if (sequence.size() != 2) 1.151 ++ bool needToEmulate = false; 1.152 ++ 1.153 ++ if (sequence.size() == 2) { 1.154 ++ TIntermTyped* param1 = sequence[0]->getAsTyped(); 1.155 ++ TIntermTyped* param2 = sequence[1]->getAsTyped(); 1.156 ++ if (!param1 || !param2) 1.157 ++ return true; 1.158 ++ needToEmulate = mEmulator.SetFunctionCalled( 1.159 ++ node->getOp(), param1->getType(), param2->getType()); 1.160 ++ } else if (sequence.size() == 3) { 1.161 ++ TIntermTyped* param1 = sequence[0]->getAsTyped(); 1.162 ++ TIntermTyped* param2 = sequence[1]->getAsTyped(); 1.163 ++ TIntermTyped* param3 = sequence[2]->getAsTyped(); 1.164 ++ if (!param1 || !param2 || !param3) 1.165 ++ return true; 1.166 ++ needToEmulate = mEmulator.SetFunctionCalled( 1.167 ++ node->getOp(), param1->getType(), param2->getType(), param3->getType()); 1.168 ++ } else { 1.169 + return true; 1.170 +- TIntermTyped* param1 = sequence[0]->getAsTyped(); 1.171 +- TIntermTyped* param2 = sequence[1]->getAsTyped(); 1.172 +- if (!param1 || !param2) 1.173 +- return true; 1.174 +- bool needToEmulate = mEmulator.SetFunctionCalled( 1.175 +- node->getOp(), param1->getType(), param2->getType()); 1.176 ++ } 1.177 ++ 1.178 + if (needToEmulate) 1.179 + node->setUseEmulatedFunction(); 1.180 + } 1.181 + return true; 1.182 + } 1.183 + 1.184 + private: 1.185 + BuiltInFunctionEmulator& mEmulator; 1.186 +@@ -286,16 +326,23 @@ bool BuiltInFunctionEmulator::SetFunctio 1.187 + bool BuiltInFunctionEmulator::SetFunctionCalled( 1.188 + TOperator op, const TType& param1, const TType& param2) 1.189 + { 1.190 + TBuiltInFunction function = IdentifyFunction(op, param1, param2); 1.191 + return SetFunctionCalled(function); 1.192 + } 1.193 + 1.194 + bool BuiltInFunctionEmulator::SetFunctionCalled( 1.195 ++ TOperator op, const TType& param1, const TType& param2, const TType& param3) 1.196 ++{ 1.197 ++ TBuiltInFunction function = IdentifyFunction(op, param1, param2, param3); 1.198 ++ return SetFunctionCalled(function); 1.199 ++} 1.200 ++ 1.201 ++bool BuiltInFunctionEmulator::SetFunctionCalled( 1.202 + BuiltInFunctionEmulator::TBuiltInFunction function) { 1.203 + if (function == TFunctionUnknown || mFunctionMask[function] == false) 1.204 + return false; 1.205 + for (size_t i = 0; i < mFunctions.size(); ++i) { 1.206 + if (mFunctions[i] == function) 1.207 + return true; 1.208 + } 1.209 + mFunctions.push_back(function); 1.210 +@@ -377,16 +424,44 @@ BuiltInFunctionEmulator::IdentifyFunctio 1.211 + } 1.212 + if (function == TFunctionUnknown) 1.213 + return TFunctionUnknown; 1.214 + if (param1.isVector()) 1.215 + function += param1.getNominalSize() - 1; 1.216 + return static_cast<TBuiltInFunction>(function); 1.217 + } 1.218 + 1.219 ++BuiltInFunctionEmulator::TBuiltInFunction 1.220 ++BuiltInFunctionEmulator::IdentifyFunction( 1.221 ++ TOperator op, const TType& param1, const TType& param2, const TType& param3) 1.222 ++{ 1.223 ++ // Check that all params have the same type, length, 1.224 ++ // and that they're not too large. 1.225 ++ if (param1.isVector() != param2.isVector() || 1.226 ++ param2.isVector() != param3.isVector() || 1.227 ++ param1.getNominalSize() != param2.getNominalSize() || 1.228 ++ param2.getNominalSize() != param3.getNominalSize() || 1.229 ++ param1.getNominalSize() > 4) 1.230 ++ return TFunctionUnknown; 1.231 ++ 1.232 ++ unsigned int function = TFunctionUnknown; 1.233 ++ switch (op) { 1.234 ++ case EOpFaceForward: 1.235 ++ function = TFunctionFaceForward1_1_1; 1.236 ++ break; 1.237 ++ default: 1.238 ++ break; 1.239 ++ } 1.240 ++ if (function == TFunctionUnknown) 1.241 ++ return TFunctionUnknown; 1.242 ++ if (param1.isVector()) 1.243 ++ function += param1.getNominalSize() - 1; 1.244 ++ return static_cast<TBuiltInFunction>(function); 1.245 ++} 1.246 ++ 1.247 + void BuiltInFunctionEmulator::MarkBuiltInFunctionsForEmulation( 1.248 + TIntermNode* root) 1.249 + { 1.250 + ASSERT(root); 1.251 + 1.252 + BuiltInFunctionEmulationMarker marker(*this); 1.253 + root->traverse(&marker); 1.254 + } 1.255 +diff --git a/gfx/angle/src/compiler/BuiltInFunctionEmulator.h b/gfx/angle/src/compiler/BuiltInFunctionEmulator.h 1.256 +--- a/gfx/angle/src/compiler/BuiltInFunctionEmulator.h 1.257 ++++ b/gfx/angle/src/compiler/BuiltInFunctionEmulator.h 1.258 +@@ -23,16 +23,18 @@ public: 1.259 + // Records that a function is called by the shader and might needs to be 1.260 + // emulated. If the function's group is not in mFunctionGroupFilter, this 1.261 + // becomes an no-op. 1.262 + // Returns true if the function call needs to be replaced with an emulated 1.263 + // one. 1.264 + bool SetFunctionCalled(TOperator op, const TType& param); 1.265 + bool SetFunctionCalled( 1.266 + TOperator op, const TType& param1, const TType& param2); 1.267 ++ bool SetFunctionCalled( 1.268 ++ TOperator op, const TType& param1, const TType& param2, const TType& param3); 1.269 + 1.270 + // Output function emulation definition. This should be before any other 1.271 + // shader source. 1.272 + void OutputEmulatedFunctionDefinition(TInfoSinkBase& out, bool withPrecision) const; 1.273 + 1.274 + void MarkBuiltInFunctionsForEmulation(TIntermNode* root); 1.275 + 1.276 + void Cleanup(); 1.277 +@@ -55,16 +57,21 @@ private: 1.278 + TFunctionDistance3_3, // vec3 distance(vec3, vec3); 1.279 + TFunctionDistance4_4, // vec4 distance(vec4, vec4); 1.280 + 1.281 + TFunctionDot1_1, // float dot(float, float); 1.282 + TFunctionDot2_2, // vec2 dot(vec2, vec2); 1.283 + TFunctionDot3_3, // vec3 dot(vec3, vec3); 1.284 + TFunctionDot4_4, // vec4 dot(vec4, vec4); 1.285 + 1.286 ++ TFunctionFaceForward1_1_1, // float faceforward(float, float, float); 1.287 ++ TFunctionFaceForward2_2_2, // vec2 faceforward(vec2, vec2, vec2); 1.288 ++ TFunctionFaceForward3_3_3, // vec3 faceforward(vec3, vec3, vec3); 1.289 ++ TFunctionFaceForward4_4_4, // vec4 faceforward(vec4, vec4, vec4); 1.290 ++ 1.291 + TFunctionLength1, // float length(float); 1.292 + TFunctionLength2, // float length(vec2); 1.293 + TFunctionLength3, // float length(vec3); 1.294 + TFunctionLength4, // float length(vec4); 1.295 + 1.296 + TFunctionNormalize1, // float normalize(float); 1.297 + TFunctionNormalize2, // vec2 normalize(vec2); 1.298 + TFunctionNormalize3, // vec3 normalize(vec3); 1.299 +@@ -76,16 +83,18 @@ private: 1.300 + TFunctionReflect4_4, // vec4 reflect(vec4, vec4); 1.301 + 1.302 + TFunctionUnknown 1.303 + }; 1.304 + 1.305 + TBuiltInFunction IdentifyFunction(TOperator op, const TType& param); 1.306 + TBuiltInFunction IdentifyFunction( 1.307 + TOperator op, const TType& param1, const TType& param2); 1.308 ++ TBuiltInFunction IdentifyFunction( 1.309 ++ TOperator op, const TType& param1, const TType& param2, const TType& param3); 1.310 + 1.311 + bool SetFunctionCalled(TBuiltInFunction function); 1.312 + 1.313 + std::vector<TBuiltInFunction> mFunctions; 1.314 + 1.315 + const bool* mFunctionMask; // a boolean flag for each function. 1.316 + const char** mFunctionSource; 1.317 + };