Skip to content

Commit 3ef11ff

Browse files
committed
Fix GLES2 emulated integer functions op_and(), op_or() and op_xor() to work properly for negative input values, and optimize to avoid control flow.
1 parent 45cd512 commit 3ef11ff

File tree

1 file changed

+4
-10
lines changed

1 file changed

+4
-10
lines changed

src/toGLSL.cpp

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1053,28 +1053,22 @@ void ToGLSL::UseExtraFunctionDependency(const std::string &name)
10531053
}
10541054
else if (name == "op_modi")
10551055
{
1056-
bformata(code, "const int BITWISE_BIT_COUNT = 32;\nint op_modi(int x, int y) { return x - y * (x / y); }\n");
1056+
bformata(code, "int op_modi(int x, int y) { return x - y * (x / y); }\n");
10571057
PrintComponentWrapper2(code, "op_modi", "ivec2", "ivec3", "ivec4");
10581058
}
10591059
else if (name == "op_and")
10601060
{
1061-
UseExtraFunctionDependency("op_modi");
1062-
1063-
bformata(code, "int op_and(int a, int b) { int result = 0; int n = 1; for (int i = 0; i < BITWISE_BIT_COUNT; i++) { if ((op_modi(a, 2) != 0) && (op_modi(b, 2) != 0)) { result += n; } a = a / 2; b = b / 2; n = n * 2; if (!(a > 0 && b > 0)) { break; } } return result; }\n");
1061+
bformata(code, "int op_and(int a, int b) { int result = (a < 0 && b < 0) ? -2147483648 : 0; if (a < 0) a -= -2147483648; if (b < 0) b -= -2147483648; int n = 1; ivec2 ab = ivec2(a, b); for (int i = 0; i < 31; i++) { ivec2 ab_div = ab / 2; ivec2 ab_rem = ab - ab_div*2; result += n * ab_rem.x * ab_rem.y; ab = ab_div; n += n; } return result; }\n");
10641062
PrintComponentWrapper2(code, "op_and", "ivec2", "ivec3", "ivec4");
10651063
}
10661064
else if (name == "op_or")
10671065
{
1068-
UseExtraFunctionDependency("op_modi");
1069-
1070-
bformata(code, "int op_or(int a, int b) { int result = 0; int n = 1; for (int i = 0; i < BITWISE_BIT_COUNT; i++) { if ((op_modi(a, 2) != 0) || (op_modi(b, 2) != 0)) { result += n; } a = a / 2; b = b / 2; n = n * 2; if (!(a > 0 || b > 0)) { break; } } return result; }\n");
1066+
bformata(code, "int op_or(int a, int b) { int result = (a < 0 || b < 0) ? -2147483648 : 0; if (a < 0) a -= -2147483648; if (b < 0) b -= -2147483648; int n = 1; ivec2 ab = ivec2(a, b); for (int i = 0; i < 31; i++) { ivec2 ab_div = ab / 2; ivec2 ab_rem = ab - ab_div*2; result += n * (ab_rem.x + ab_rem.y - ab_rem.x*ab_rem.y); ab = ab_div; n += n; } return result; }\n");
10711067
PrintComponentWrapper2(code, "op_or", "ivec2", "ivec3", "ivec4");
10721068
}
10731069
else if (name == "op_xor")
10741070
{
1075-
UseExtraFunctionDependency("op_and");
1076-
1077-
bformata(code, "int op_xor(int a, int b) { return (a + b - 2 * op_and(a, b)); }\n");
1071+
bformata(code, "int op_xor(int a, int b) { int result = 0; if (a < 0) { a -= -2147483648; result -= -2147483648; } if (b < 0) { b -= -2147483648; result -= -2147483648; } int n = 1; ivec2 ab = ivec2(a, b); for (int i = 0; i < 31; i++) { ivec2 ab_div = ab / 2; ivec2 ab_rem = ab - ab_div*2; result += n * int(ab_rem.x != ab_rem.y); ab = ab_div; n += n; } return result; }\n");
10781072
PrintComponentWrapper2(code, "op_xor", "ivec2", "ivec3", "ivec4");
10791073
}
10801074
else if (name == "op_shr")

0 commit comments

Comments
 (0)