Implement Metal polyfill for sign(genIType).

This uses nested selects to compute `(x > 0) ? 1 : (x < 0) ? -1 : 0`.

Change-Id: I1a87fc8506767bb0a9dd77ba2193b330e0a4d0a2
Bug: skia:12898, skia:11209
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/503486
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: John Stiles <johnstiles@google.com>
This commit is contained in:
John Stiles 2022-02-02 18:05:38 -05:00 committed by SkCQ
parent a83a5cf287
commit d4fff483dd
3 changed files with 36 additions and 2 deletions

View File

@ -847,6 +847,36 @@ bool MetalCodeGenerator::writeIntrinsicCall(const FunctionCall& c, IntrinsicKind
this->write("(0)))");
return true;
}
case k_sign_IntrinsicKind: {
if (arguments[0]->type().componentType().isInteger()) {
// Create a temp variable to store the expression, to avoid double-evaluating it.
std::string skTemp = this->getTempVariable(arguments[0]->type());
std::string exprType = this->typeName(arguments[0]->type());
// (_skTemp = (.....),
this->write("(");
this->write(skTemp);
this->write(" = (");
this->writeExpression(*arguments[0], Precedence::kSequence);
this->write("), ");
// ... select(select(int4(0), int4(-1), _skTemp < 0), int4(1), _skTemp > 0))
this->write("select(select(");
this->write(exprType);
this->write("(0), ");
this->write(exprType);
this->write("(-1), ");
this->write(skTemp);
this->write(" < 0), ");
this->write(exprType);
this->write("(1), ");
this->write(skTemp);
this->write(" > 0))");
} else {
this->writeSimpleIntrinsic(c);
}
return true;
}
case k_matrixCompMult_IntrinsicKind: {
this->writeMatrixCompMult();
this->writeSimpleIntrinsic(c);

View File

@ -335,6 +335,7 @@ SKSL_TEST_ES3(SkSLIntrinsicOuterProduct, "intrinsics/OuterProduct.sksl")
SKSL_TEST_ES3(SkSLIntrinsicRound, "intrinsics/Round.sksl")
SKSL_TEST_ES3(SkSLIntrinsicRoundEven, "intrinsics/RoundEven.sksl")
SKSL_TEST(SkSLIntrinsicSignFloat, "intrinsics/SignFloat.sksl")
SKSL_TEST_ES3(SkSLIntrinsicSignInt, "intrinsics/SignInt.sksl")
SKSL_TEST(SkSLIntrinsicStep, "intrinsics/Step.sksl")
SKSL_TEST_ES3(SkSLIntrinsicTrunc, "intrinsics/Trunc.sksl")
SKSL_TEST_ES3(SkSLIntrinsicTranspose, "intrinsics/Transpose.sksl")
@ -444,5 +445,4 @@ SKSL_TEST(SkSLIntrinsicAbsInt, "intrinsics/AbsInt.sksl")
SKSL_TEST(SkSLIntrinsicMaxInt, "intrinsics/MaxInt.sksl")
SKSL_TEST(SkSLIntrinsicMinInt, "intrinsics/MinInt.sksl")
SKSL_TEST(SkSLIntrinsicMixBool, "intrinsics/MixBool.sksl")
SKSL_TEST(SkSLIntrinsicSignInt, "intrinsics/SignInt.sksl")
*/

View File

@ -14,7 +14,11 @@ struct Outputs {
fragment Outputs fragmentMain(Inputs _in [[stage_in]], constant Uniforms& _uniforms [[buffer(0)]], bool _frontFacing [[front_facing]], float4 _fragCoord [[position]]) {
Outputs _out;
(void)_out;
int _skTemp0;
int2 _skTemp1;
int3 _skTemp2;
int4 _skTemp3;
int4 expected = int4(-1, 0, 0, 1);
_out.sk_FragColor = ((((((sign(int(_uniforms.testInputs.x)) == expected.x && all(sign(int2(_uniforms.testInputs.xy)) == expected.xy)) && all(sign(int3(_uniforms.testInputs.xyz)) == expected.xyz)) && all(sign(int4(_uniforms.testInputs)) == expected)) && -1 == expected.x) && all(int2(-1, 0) == expected.xy)) && all(int3(-1, 0, 0) == expected.xyz)) && all(int4(-1, 0, 0, 1) == expected) ? _uniforms.colorGreen : _uniforms.colorRed;
_out.sk_FragColor = (((((((_skTemp0 = (int(_uniforms.testInputs.x)), select(select(int(0), int(-1), _skTemp0 < 0), int(1), _skTemp0 > 0)) == expected.x && all((_skTemp1 = (int2(_uniforms.testInputs.xy)), select(select(int2(0), int2(-1), _skTemp1 < 0), int2(1), _skTemp1 > 0)) == expected.xy)) && all((_skTemp2 = (int3(_uniforms.testInputs.xyz)), select(select(int3(0), int3(-1), _skTemp2 < 0), int3(1), _skTemp2 > 0)) == expected.xyz)) && all((_skTemp3 = (int4(_uniforms.testInputs)), select(select(int4(0), int4(-1), _skTemp3 < 0), int4(1), _skTemp3 > 0)) == expected)) && -1 == expected.x) && all(int2(-1, 0) == expected.xy)) && all(int3(-1, 0, 0) == expected.xyz)) && all(int4(-1, 0, 0, 1) == expected) ? _uniforms.colorGreen : _uniforms.colorRed;
return _out;
}