mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
315 lines
12 KiB
Diff
315 lines
12 KiB
Diff
|
From: Jeff Gilbert <jgilbert@mozilla.com>
|
||
|
Bug 771406 - Add emulation for GLSL faceforward() to ANGLE - r=bjacob
|
||
|
|
||
|
diff --git a/gfx/angle/src/compiler/BuiltInFunctionEmulator.cpp b/gfx/angle/src/compiler/BuiltInFunctionEmulator.cpp
|
||
|
--- a/gfx/angle/src/compiler/BuiltInFunctionEmulator.cpp
|
||
|
+++ b/gfx/angle/src/compiler/BuiltInFunctionEmulator.cpp
|
||
|
@@ -26,16 +26,22 @@ const char* kFunctionEmulationVertexSour
|
||
|
"#error no emulation for distance(vec3, vec3)",
|
||
|
"#error no emulation for distance(vec4, vec4)",
|
||
|
|
||
|
"#define webgl_dot_emu(x, y) ((x) * (y))",
|
||
|
"#error no emulation for dot(vec2, vec2)",
|
||
|
"#error no emulation for dot(vec3, vec3)",
|
||
|
"#error no emulation for dot(vec4, vec4)",
|
||
|
|
||
|
+ // |faceforward(N, I, Nref)| is |dot(NRef, I) < 0 ? N : -N|
|
||
|
+ "#define webgl_faceforward_emu(N, I, Nref) (((Nref) * (I) < 0.0) ? (N) : -(N))",
|
||
|
+ "#error no emulation for faceforward(vec2, vec2, vec2)",
|
||
|
+ "#error no emulation for faceforward(vec3, vec3, vec3)",
|
||
|
+ "#error no emulation for faceforward(vec4, vec4, vec4)",
|
||
|
+
|
||
|
"#define webgl_length_emu(x) ((x) >= 0.0 ? (x) : -(x))",
|
||
|
"#error no emulation for length(vec2)",
|
||
|
"#error no emulation for length(vec3)",
|
||
|
"#error no emulation for length(vec4)",
|
||
|
|
||
|
"#define webgl_normalize_emu(x) ((x) == 0.0 ? 0.0 : ((x) > 0.0 ? 1.0 : -1.0))",
|
||
|
"#error no emulation for normalize(vec2)",
|
||
|
"#error no emulation for normalize(vec3)",
|
||
|
@@ -58,16 +64,22 @@ const char* kFunctionEmulationFragmentSo
|
||
|
"#error no emulation for distance(vec3, vec3)",
|
||
|
"#error no emulation for distance(vec4, vec4)",
|
||
|
|
||
|
"#define webgl_dot_emu(x, y) ((x) * (y))",
|
||
|
"#error no emulation for dot(vec2, vec2)",
|
||
|
"#error no emulation for dot(vec3, vec3)",
|
||
|
"#error no emulation for dot(vec4, vec4)",
|
||
|
|
||
|
+ // |faceforward(N, I, Nref)| is |dot(NRef, I) < 0 ? N : -N|
|
||
|
+ "#define webgl_faceforward_emu(N, I, Nref) (((Nref) * (I) < 0.0) ? (N) : -(N))",
|
||
|
+ "#error no emulation for faceforward(vec2, vec2, vec2)",
|
||
|
+ "#error no emulation for faceforward(vec3, vec3, vec3)",
|
||
|
+ "#error no emulation for faceforward(vec4, vec4, vec4)",
|
||
|
+
|
||
|
"#define webgl_length_emu(x) ((x) >= 0.0 ? (x) : -(x))",
|
||
|
"#error no emulation for length(vec2)",
|
||
|
"#error no emulation for length(vec3)",
|
||
|
"#error no emulation for length(vec4)",
|
||
|
|
||
|
"#define webgl_normalize_emu(x) ((x) == 0.0 ? 0.0 : ((x) > 0.0 ? 1.0 : -1.0))",
|
||
|
"#error no emulation for normalize(vec2)",
|
||
|
"#error no emulation for normalize(vec3)",
|
||
|
@@ -89,16 +101,20 @@ const bool kFunctionEmulationVertexMask[
|
||
|
true, // TFunctionDistance1_1
|
||
|
false, // TFunctionDistance2_2
|
||
|
false, // TFunctionDistance3_3
|
||
|
false, // TFunctionDistance4_4
|
||
|
true, // TFunctionDot1_1
|
||
|
false, // TFunctionDot2_2
|
||
|
false, // TFunctionDot3_3
|
||
|
false, // TFunctionDot4_4
|
||
|
+ true, // TFunctionFaceForward1_1_1
|
||
|
+ false, // TFunctionFaceForward2_2_2
|
||
|
+ false, // TFunctionFaceForward3_3_3
|
||
|
+ false, // TFunctionFaceForward4_4_4
|
||
|
true, // TFunctionLength1
|
||
|
false, // TFunctionLength2
|
||
|
false, // TFunctionLength3
|
||
|
false, // TFunctionLength4
|
||
|
true, // TFunctionNormalize1
|
||
|
false, // TFunctionNormalize2
|
||
|
false, // TFunctionNormalize3
|
||
|
false, // TFunctionNormalize4
|
||
|
@@ -115,16 +131,20 @@ const bool kFunctionEmulationVertexMask[
|
||
|
false, // TFunctionDistance1_1
|
||
|
false, // TFunctionDistance2_2
|
||
|
false, // TFunctionDistance3_3
|
||
|
false, // TFunctionDistance4_4
|
||
|
false, // TFunctionDot1_1
|
||
|
false, // TFunctionDot2_2
|
||
|
false, // TFunctionDot3_3
|
||
|
false, // TFunctionDot4_4
|
||
|
+ false, // TFunctionFaceForward1_1_1
|
||
|
+ false, // TFunctionFaceForward2_2_2
|
||
|
+ false, // TFunctionFaceForward3_3_3
|
||
|
+ false, // TFunctionFaceForward4_4_4
|
||
|
false, // TFunctionLength1
|
||
|
false, // TFunctionLength2
|
||
|
false, // TFunctionLength3
|
||
|
false, // TFunctionLength4
|
||
|
false, // TFunctionNormalize1
|
||
|
false, // TFunctionNormalize2
|
||
|
false, // TFunctionNormalize3
|
||
|
false, // TFunctionNormalize4
|
||
|
@@ -146,16 +166,20 @@ const bool kFunctionEmulationFragmentMas
|
||
|
true, // TFunctionDistance1_1
|
||
|
false, // TFunctionDistance2_2
|
||
|
false, // TFunctionDistance3_3
|
||
|
false, // TFunctionDistance4_4
|
||
|
true, // TFunctionDot1_1
|
||
|
false, // TFunctionDot2_2
|
||
|
false, // TFunctionDot3_3
|
||
|
false, // TFunctionDot4_4
|
||
|
+ true, // TFunctionFaceForward1_1_1
|
||
|
+ false, // TFunctionFaceForward2_2_2
|
||
|
+ false, // TFunctionFaceForward3_3_3
|
||
|
+ false, // TFunctionFaceForward4_4_4
|
||
|
true, // TFunctionLength1
|
||
|
false, // TFunctionLength2
|
||
|
false, // TFunctionLength3
|
||
|
false, // TFunctionLength4
|
||
|
true, // TFunctionNormalize1
|
||
|
false, // TFunctionNormalize2
|
||
|
false, // TFunctionNormalize3
|
||
|
false, // TFunctionNormalize4
|
||
|
@@ -172,16 +196,20 @@ const bool kFunctionEmulationFragmentMas
|
||
|
false, // TFunctionDistance1_1
|
||
|
false, // TFunctionDistance2_2
|
||
|
false, // TFunctionDistance3_3
|
||
|
false, // TFunctionDistance4_4
|
||
|
false, // TFunctionDot1_1
|
||
|
false, // TFunctionDot2_2
|
||
|
false, // TFunctionDot3_3
|
||
|
false, // TFunctionDot4_4
|
||
|
+ false, // TFunctionFaceForward1_1_1
|
||
|
+ false, // TFunctionFaceForward2_2_2
|
||
|
+ false, // TFunctionFaceForward3_3_3
|
||
|
+ false, // TFunctionFaceForward4_4_4
|
||
|
false, // TFunctionLength1
|
||
|
false, // TFunctionLength2
|
||
|
false, // TFunctionLength3
|
||
|
false, // TFunctionLength4
|
||
|
false, // TFunctionNormalize1
|
||
|
false, // TFunctionNormalize2
|
||
|
false, // TFunctionNormalize3
|
||
|
false, // TFunctionNormalize4
|
||
|
@@ -239,25 +267,37 @@ public:
|
||
|
case EOpReflect:
|
||
|
case EOpRefract:
|
||
|
case EOpMul:
|
||
|
break;
|
||
|
default:
|
||
|
return true;
|
||
|
};
|
||
|
const TIntermSequence& sequence = node->getSequence();
|
||
|
- // Right now we only handle built-in functions with two parameters.
|
||
|
- if (sequence.size() != 2)
|
||
|
+ bool needToEmulate = false;
|
||
|
+
|
||
|
+ if (sequence.size() == 2) {
|
||
|
+ TIntermTyped* param1 = sequence[0]->getAsTyped();
|
||
|
+ TIntermTyped* param2 = sequence[1]->getAsTyped();
|
||
|
+ if (!param1 || !param2)
|
||
|
+ return true;
|
||
|
+ needToEmulate = mEmulator.SetFunctionCalled(
|
||
|
+ node->getOp(), param1->getType(), param2->getType());
|
||
|
+ } else if (sequence.size() == 3) {
|
||
|
+ TIntermTyped* param1 = sequence[0]->getAsTyped();
|
||
|
+ TIntermTyped* param2 = sequence[1]->getAsTyped();
|
||
|
+ TIntermTyped* param3 = sequence[2]->getAsTyped();
|
||
|
+ if (!param1 || !param2 || !param3)
|
||
|
+ return true;
|
||
|
+ needToEmulate = mEmulator.SetFunctionCalled(
|
||
|
+ node->getOp(), param1->getType(), param2->getType(), param3->getType());
|
||
|
+ } else {
|
||
|
return true;
|
||
|
- TIntermTyped* param1 = sequence[0]->getAsTyped();
|
||
|
- TIntermTyped* param2 = sequence[1]->getAsTyped();
|
||
|
- if (!param1 || !param2)
|
||
|
- return true;
|
||
|
- bool needToEmulate = mEmulator.SetFunctionCalled(
|
||
|
- node->getOp(), param1->getType(), param2->getType());
|
||
|
+ }
|
||
|
+
|
||
|
if (needToEmulate)
|
||
|
node->setUseEmulatedFunction();
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
BuiltInFunctionEmulator& mEmulator;
|
||
|
@@ -286,16 +326,23 @@ bool BuiltInFunctionEmulator::SetFunctio
|
||
|
bool BuiltInFunctionEmulator::SetFunctionCalled(
|
||
|
TOperator op, const TType& param1, const TType& param2)
|
||
|
{
|
||
|
TBuiltInFunction function = IdentifyFunction(op, param1, param2);
|
||
|
return SetFunctionCalled(function);
|
||
|
}
|
||
|
|
||
|
bool BuiltInFunctionEmulator::SetFunctionCalled(
|
||
|
+ TOperator op, const TType& param1, const TType& param2, const TType& param3)
|
||
|
+{
|
||
|
+ TBuiltInFunction function = IdentifyFunction(op, param1, param2, param3);
|
||
|
+ return SetFunctionCalled(function);
|
||
|
+}
|
||
|
+
|
||
|
+bool BuiltInFunctionEmulator::SetFunctionCalled(
|
||
|
BuiltInFunctionEmulator::TBuiltInFunction function) {
|
||
|
if (function == TFunctionUnknown || mFunctionMask[function] == false)
|
||
|
return false;
|
||
|
for (size_t i = 0; i < mFunctions.size(); ++i) {
|
||
|
if (mFunctions[i] == function)
|
||
|
return true;
|
||
|
}
|
||
|
mFunctions.push_back(function);
|
||
|
@@ -377,16 +424,44 @@ BuiltInFunctionEmulator::IdentifyFunctio
|
||
|
}
|
||
|
if (function == TFunctionUnknown)
|
||
|
return TFunctionUnknown;
|
||
|
if (param1.isVector())
|
||
|
function += param1.getNominalSize() - 1;
|
||
|
return static_cast<TBuiltInFunction>(function);
|
||
|
}
|
||
|
|
||
|
+BuiltInFunctionEmulator::TBuiltInFunction
|
||
|
+BuiltInFunctionEmulator::IdentifyFunction(
|
||
|
+ TOperator op, const TType& param1, const TType& param2, const TType& param3)
|
||
|
+{
|
||
|
+ // Check that all params have the same type, length,
|
||
|
+ // and that they're not too large.
|
||
|
+ if (param1.isVector() != param2.isVector() ||
|
||
|
+ param2.isVector() != param3.isVector() ||
|
||
|
+ param1.getNominalSize() != param2.getNominalSize() ||
|
||
|
+ param2.getNominalSize() != param3.getNominalSize() ||
|
||
|
+ param1.getNominalSize() > 4)
|
||
|
+ return TFunctionUnknown;
|
||
|
+
|
||
|
+ unsigned int function = TFunctionUnknown;
|
||
|
+ switch (op) {
|
||
|
+ case EOpFaceForward:
|
||
|
+ function = TFunctionFaceForward1_1_1;
|
||
|
+ break;
|
||
|
+ default:
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ if (function == TFunctionUnknown)
|
||
|
+ return TFunctionUnknown;
|
||
|
+ if (param1.isVector())
|
||
|
+ function += param1.getNominalSize() - 1;
|
||
|
+ return static_cast<TBuiltInFunction>(function);
|
||
|
+}
|
||
|
+
|
||
|
void BuiltInFunctionEmulator::MarkBuiltInFunctionsForEmulation(
|
||
|
TIntermNode* root)
|
||
|
{
|
||
|
ASSERT(root);
|
||
|
|
||
|
BuiltInFunctionEmulationMarker marker(*this);
|
||
|
root->traverse(&marker);
|
||
|
}
|
||
|
diff --git a/gfx/angle/src/compiler/BuiltInFunctionEmulator.h b/gfx/angle/src/compiler/BuiltInFunctionEmulator.h
|
||
|
--- a/gfx/angle/src/compiler/BuiltInFunctionEmulator.h
|
||
|
+++ b/gfx/angle/src/compiler/BuiltInFunctionEmulator.h
|
||
|
@@ -23,16 +23,18 @@ public:
|
||
|
// Records that a function is called by the shader and might needs to be
|
||
|
// emulated. If the function's group is not in mFunctionGroupFilter, this
|
||
|
// becomes an no-op.
|
||
|
// Returns true if the function call needs to be replaced with an emulated
|
||
|
// one.
|
||
|
bool SetFunctionCalled(TOperator op, const TType& param);
|
||
|
bool SetFunctionCalled(
|
||
|
TOperator op, const TType& param1, const TType& param2);
|
||
|
+ bool SetFunctionCalled(
|
||
|
+ TOperator op, const TType& param1, const TType& param2, const TType& param3);
|
||
|
|
||
|
// Output function emulation definition. This should be before any other
|
||
|
// shader source.
|
||
|
void OutputEmulatedFunctionDefinition(TInfoSinkBase& out, bool withPrecision) const;
|
||
|
|
||
|
void MarkBuiltInFunctionsForEmulation(TIntermNode* root);
|
||
|
|
||
|
void Cleanup();
|
||
|
@@ -55,16 +57,21 @@ private:
|
||
|
TFunctionDistance3_3, // vec3 distance(vec3, vec3);
|
||
|
TFunctionDistance4_4, // vec4 distance(vec4, vec4);
|
||
|
|
||
|
TFunctionDot1_1, // float dot(float, float);
|
||
|
TFunctionDot2_2, // vec2 dot(vec2, vec2);
|
||
|
TFunctionDot3_3, // vec3 dot(vec3, vec3);
|
||
|
TFunctionDot4_4, // vec4 dot(vec4, vec4);
|
||
|
|
||
|
+ TFunctionFaceForward1_1_1, // float faceforward(float, float, float);
|
||
|
+ TFunctionFaceForward2_2_2, // vec2 faceforward(vec2, vec2, vec2);
|
||
|
+ TFunctionFaceForward3_3_3, // vec3 faceforward(vec3, vec3, vec3);
|
||
|
+ TFunctionFaceForward4_4_4, // vec4 faceforward(vec4, vec4, vec4);
|
||
|
+
|
||
|
TFunctionLength1, // float length(float);
|
||
|
TFunctionLength2, // float length(vec2);
|
||
|
TFunctionLength3, // float length(vec3);
|
||
|
TFunctionLength4, // float length(vec4);
|
||
|
|
||
|
TFunctionNormalize1, // float normalize(float);
|
||
|
TFunctionNormalize2, // vec2 normalize(vec2);
|
||
|
TFunctionNormalize3, // vec3 normalize(vec3);
|
||
|
@@ -76,16 +83,18 @@ private:
|
||
|
TFunctionReflect4_4, // vec4 reflect(vec4, vec4);
|
||
|
|
||
|
TFunctionUnknown
|
||
|
};
|
||
|
|
||
|
TBuiltInFunction IdentifyFunction(TOperator op, const TType& param);
|
||
|
TBuiltInFunction IdentifyFunction(
|
||
|
TOperator op, const TType& param1, const TType& param2);
|
||
|
+ TBuiltInFunction IdentifyFunction(
|
||
|
+ TOperator op, const TType& param1, const TType& param2, const TType& param3);
|
||
|
|
||
|
bool SetFunctionCalled(TBuiltInFunction function);
|
||
|
|
||
|
std::vector<TBuiltInFunction> mFunctions;
|
||
|
|
||
|
const bool* mFunctionMask; // a boolean flag for each function.
|
||
|
const char** mFunctionSource;
|
||
|
};
|