Add support for float/int bitcast intrinsics in Metal.

Change-Id: I7af94d89d349b67b2c070179324fcad7b62e0d1e
Bug: skia:11071
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/342758
Commit-Queue: John Stiles <johnstiles@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
This commit is contained in:
John Stiles 2020-12-10 10:34:27 -05:00 committed by Skia Commit-Bot
parent cc9ff0074e
commit f64e4075f2
6 changed files with 33 additions and 23 deletions

View File

@ -381,6 +381,10 @@ String MetalCodeGenerator::getOutParamHelper(const FunctionCall& call,
return name;
}
String MetalCodeGenerator::getBitcastIntrinsic(const Type& outType) {
return "as_type<" + outType.displayName() + ">";
}
void MetalCodeGenerator::writeFunctionCall(const FunctionCall& c) {
const FunctionDeclaration& function = c.function();
const ExpressionArray& arguments = c.arguments();
@ -390,34 +394,38 @@ void MetalCodeGenerator::writeFunctionCall(const FunctionCall& c) {
return;
}
String name = function.name();
bool builtin = function.isBuiltin();
if (builtin && name == "atan" && arguments.size() == 2) {
name = "atan2";
} else if (builtin && name == "inversesqrt") {
name = "rsqrt";
} else if (builtin && name == "inverse") {
SkASSERT(arguments.size() == 1);
name = this->getInverseHack(*arguments[0]);
} else if (builtin && name == "dFdx") {
name = "dfdx";
} else if (builtin && name == "dFdy") {
// Flipping Y also negates the Y derivatives.
if (fProgram.fSettings.fFlipY) {
this->write("-");
if (function.isBuiltin()) {
if (name == "atan" && arguments.size() == 2) {
name = "atan2";
} else if (name == "inversesqrt") {
name = "rsqrt";
} else if (name == "inverse") {
SkASSERT(arguments.size() == 1);
name = this->getInverseHack(*arguments[0]);
} else if (name == "dFdx") {
name = "dfdx";
} else if (name == "dFdy") {
// Flipping Y also negates the Y derivatives.
if (fProgram.fSettings.fFlipY) {
this->write("-");
}
name = "dfdy";
} else if (name == "floatBitsToInt" || name == "floatBitsToUint" ||
name == "intBitsToFloat" || name == "uintBitsToFloat") {
name = this->getBitcastIntrinsic(c.type());
}
name = "dfdy";
}
// GLSL supports passing swizzled variables to out params; Metal doesn't. Walk the list of
// parameters and see if any are out parameters; if so, check if the passed-in expression is a
// swizzle. Take a note of all the swizzled variables that we find.
// We emulate GLSL's out-param semantics for Metal using a helper function. (Specifically,
// results are only written back to the original variable at the end of the function call; also,
// swizzles are supported, whereas Metal doesn't allow a swizzle to be passed to a `floatN&`.)
const std::vector<const Variable*>& parameters = function.parameters();
SkASSERT(arguments.size() == parameters.size());
bool foundOutParam = false;
SkSTArray<16, VariableReference*> outVars;
outVars.push_back_n(arguments.size(), (VariableReference*)nullptr);
outVars.push_back_n(arguments.count(), (VariableReference*)nullptr);
for (int index = 0; index < arguments.count(); ++index) {
// If this is an out parameter...

View File

@ -215,6 +215,8 @@ protected:
String getInverseHack(const Expression& mat);
String getBitcastIntrinsic(const Type& outType);
void writeFunctionCall(const FunctionCall& c);
bool matrixConstructHelperIsNeeded(const Constructor& c);

View File

@ -11,6 +11,6 @@ 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(floatBitsToInt(_in.a));
_out->sk_FragColor.x = float(as_type<int>(_in.a));
return *_out;
}

View File

@ -11,6 +11,6 @@ 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(floatBitsToUint(_in.a));
_out->sk_FragColor.x = float(as_type<uint>(_in.a));
return *_out;
}

View File

@ -11,6 +11,6 @@ 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 = intBitsToFloat(_in.a);
_out->sk_FragColor.x = as_type<float>(_in.a);
return *_out;
}

View File

@ -11,6 +11,6 @@ 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 = uintBitsToFloat(_in.a);
_out->sk_FragColor.x = as_type<float>(_in.a);
return *_out;
}