Add Metal support for the findLSB
intrinsic.
Change-Id: Id38a3d04fcb1904a4c666d92087b4fe14bd03a27 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/343110 Commit-Queue: John Stiles <johnstiles@google.com> Reviewed-by: Brian Osman <brianosman@google.com> Auto-Submit: John Stiles <johnstiles@google.com>
This commit is contained in:
parent
6ecee7f0f5
commit
86424eb0cf
@ -49,6 +49,7 @@ void MetalCodeGenerator::setupIntrinsics() {
|
||||
fIntrinsicMap[String("distance")] = SPECIAL(Distance);
|
||||
fIntrinsicMap[String("dot")] = SPECIAL(Dot);
|
||||
fIntrinsicMap[String("faceforward")] = SPECIAL(Faceforward);
|
||||
fIntrinsicMap[String("findLSB")] = SPECIAL(FindLSB);
|
||||
fIntrinsicMap[String("length")] = SPECIAL(Length);
|
||||
fIntrinsicMap[String("mod")] = SPECIAL(Mod);
|
||||
fIntrinsicMap[String("normalize")] = SPECIAL(Normalize);
|
||||
@ -550,6 +551,12 @@ String MetalCodeGenerator::getInverseHack(const Expression& mat) {
|
||||
return name;
|
||||
}
|
||||
|
||||
String MetalCodeGenerator::getTempVariable(const Type& type) {
|
||||
String tempVar = "_skTemp" + to_string(fVarCount++);
|
||||
this->fFunctionHeader += " " + this->typeName(type) + " " + tempVar + ";\n";
|
||||
return tempVar;
|
||||
}
|
||||
|
||||
void MetalCodeGenerator::writeSpecialIntrinsic(const FunctionCall & c, SpecialIntrinsic kind) {
|
||||
const ExpressionArray& arguments = c.arguments();
|
||||
switch (kind) {
|
||||
@ -562,8 +569,7 @@ void MetalCodeGenerator::writeSpecialIntrinsic(const FunctionCall & c, SpecialIn
|
||||
const Type& arg1Type = arguments[1]->type();
|
||||
if (arg1Type == *fContext.fFloat3_Type) {
|
||||
// have to store the vector in a temp variable to avoid double evaluating it
|
||||
String tmpVar = "tmpCoord" + to_string(fVarCount++);
|
||||
this->fFunctionHeader += " " + this->typeName(arg1Type) + " " + tmpVar + ";\n";
|
||||
String tmpVar = this->getTempVariable(arg1Type);
|
||||
this->write("(" + tmpVar + " = ");
|
||||
this->writeExpression(*arguments[1], kSequence_Precedence);
|
||||
this->write(", " + tmpVar + ".xy / " + tmpVar + ".z))");
|
||||
@ -576,10 +582,8 @@ void MetalCodeGenerator::writeSpecialIntrinsic(const FunctionCall & c, SpecialIn
|
||||
}
|
||||
case kMod_SpecialIntrinsic: {
|
||||
// fmod(x, y) in metal calculates x - y * trunc(x / y) instead of x - y * floor(x / y)
|
||||
String tmpX = "tmpX" + to_string(fVarCount++);
|
||||
String tmpY = "tmpY" + to_string(fVarCount++);
|
||||
this->fFunctionHeader += " " + this->typeName(arguments[0]->type()) +
|
||||
" " + tmpX + ", " + tmpY + ";\n";
|
||||
String tmpX = this->getTempVariable(arguments[0]->type());
|
||||
String tmpY = this->getTempVariable(arguments[0]->type());
|
||||
this->write("(" + tmpX + " = ");
|
||||
this->writeExpression(*arguments[0], kSequence_Precedence);
|
||||
this->write(", " + tmpY + " = ");
|
||||
@ -672,6 +676,30 @@ void MetalCodeGenerator::writeSpecialIntrinsic(const FunctionCall & c, SpecialIn
|
||||
this->write(") * 0.0174532925)");
|
||||
break;
|
||||
}
|
||||
case kFindLSB_SpecialIntrinsic: {
|
||||
// Create a temp variable to store the expression, to avoid double-evaluating it.
|
||||
String skTemp = this->getTempVariable(arguments[0]->type());
|
||||
String exprType = this->typeName(arguments[0]->type());
|
||||
|
||||
// ctz returns numbits(type) on zero inputs; GLSL documents it as generating -1 instead.
|
||||
// Use select to detect zero inputs and force a -1 result.
|
||||
|
||||
// (_skTemp1 = (.....), select(ctz(_skTemp1), int4(-1), _skTemp1 == int4(0)))
|
||||
this->write("(");
|
||||
this->write(skTemp);
|
||||
this->write(" = (");
|
||||
this->writeExpression(*arguments[0], kSequence_Precedence);
|
||||
this->write("), select(ctz(");
|
||||
this->write(skTemp);
|
||||
this->write("), ");
|
||||
this->write(exprType);
|
||||
this->write("(-1), ");
|
||||
this->write(skTemp);
|
||||
this->write(" == ");
|
||||
this->write(exprType);
|
||||
this->write("(0)))");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ABORT("unsupported special intrinsic kind");
|
||||
}
|
||||
|
@ -109,6 +109,7 @@ protected:
|
||||
kDistance_SpecialIntrinsic,
|
||||
kDot_SpecialIntrinsic,
|
||||
kFaceforward_SpecialIntrinsic,
|
||||
kFindLSB_SpecialIntrinsic,
|
||||
kLength_SpecialIntrinsic,
|
||||
kMod_SpecialIntrinsic,
|
||||
kNormalize_SpecialIntrinsic,
|
||||
@ -221,6 +222,8 @@ protected:
|
||||
|
||||
String getBitcastIntrinsic(const Type& outType);
|
||||
|
||||
String getTempVariable(const Type& varType);
|
||||
|
||||
void writeFunctionCall(const FunctionCall& c);
|
||||
|
||||
bool matrixConstructHelperIsNeeded(const Constructor& c);
|
||||
|
@ -13,7 +13,9 @@ struct Outputs {
|
||||
fragment Outputs fragmentMain(Inputs _in [[stage_in]], bool _frontFacing [[front_facing]], float4 _fragCoord [[position]]) {
|
||||
Outputs _outputStruct;
|
||||
thread Outputs* _out = &_outputStruct;
|
||||
_out->sk_FragColor.x = float(findLSB(_in.a));
|
||||
_out->sk_FragColor.y = float(findLSB(int(_in.b)));
|
||||
int _skTemp0;
|
||||
int _skTemp1;
|
||||
_out->sk_FragColor.x = float((_skTemp0 = (_in.a), select(ctz(_skTemp0), int(-1), _skTemp0 == int(0))));
|
||||
_out->sk_FragColor.y = float((_skTemp1 = (int(_in.b)), select(ctz(_skTemp1), int(-1), _skTemp1 == int(0))));
|
||||
return *_out;
|
||||
}
|
||||
|
@ -13,7 +13,8 @@ struct Outputs {
|
||||
fragment Outputs fragmentMain(Inputs _in [[stage_in]], bool _frontFacing [[front_facing]], float4 _fragCoord [[position]]) {
|
||||
Outputs _outputStruct;
|
||||
thread Outputs* _out = &_outputStruct;
|
||||
float tmpX0, tmpY1;
|
||||
_out->sk_FragColor.x = (tmpX0 = _in.a, tmpY1 = _in.b, tmpX0 - tmpY1 * floor(tmpX0 / tmpY1));
|
||||
float _skTemp0;
|
||||
float _skTemp1;
|
||||
_out->sk_FragColor.x = (_skTemp0 = _in.a, _skTemp1 = _in.b, _skTemp0 - _skTemp1 * floor(_skTemp0 / _skTemp1));
|
||||
return *_out;
|
||||
}
|
||||
|
@ -20,9 +20,9 @@ fragment Outputs fragmentMain(Inputs _in [[stage_in]], texture2d<float> test2D[[
|
||||
(void)_globals;
|
||||
Outputs _outputStruct;
|
||||
thread Outputs* _out = &_outputStruct;
|
||||
float3 tmpCoord0;
|
||||
float3 _skTemp0;
|
||||
_out->sk_FragColor = _globals->test2D.sample(_globals->test2DSmplr, float2(0.5));
|
||||
_out->sk_FragColor = _globals->test2DRect.sample(_globals->test2DRectSmplr, float2(0.5));
|
||||
_out->sk_FragColor = _globals->test2DRect.sample(_globals->test2DRectSmplr, (tmpCoord0 = float3(0.5), tmpCoord0.xy / tmpCoord0.z));
|
||||
_out->sk_FragColor = _globals->test2DRect.sample(_globals->test2DRectSmplr, (_skTemp0 = float3(0.5), _skTemp0.xy / _skTemp0.z));
|
||||
return *_out;
|
||||
}
|
||||
|
@ -17,9 +17,9 @@ fragment Outputs fragmentMain(Inputs _in [[stage_in]], texture2d<float> tex[[tex
|
||||
(void)_globals;
|
||||
Outputs _outputStruct;
|
||||
thread Outputs* _out = &_outputStruct;
|
||||
float3 tmpCoord0;
|
||||
float3 _skTemp0;
|
||||
float4 a = _globals->tex.sample(_globals->texSmplr, float2(0.0));
|
||||
float4 b = _globals->tex.sample(_globals->texSmplr, (tmpCoord0 = float3(0.0), tmpCoord0.xy / tmpCoord0.z));
|
||||
float4 b = _globals->tex.sample(_globals->texSmplr, (_skTemp0 = float3(0.0), _skTemp0.xy / _skTemp0.z));
|
||||
_out->sk_FragColor = float4(a.xy, b.zw);
|
||||
return *_out;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user