Fix SkSL constant propagation within nested casts.

Previously, the inner type was ignored.

Change-Id: I51d251fc38358ef889b5a3f85d5f2d23bd8cf4c5
Bug: skia:10615
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/310657
Commit-Queue: John Stiles <johnstiles@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
This commit is contained in:
John Stiles 2020-08-14 16:12:31 -04:00 committed by Skia Commit-Bot
parent 43f49b4d52
commit 4e54367db3
3 changed files with 134 additions and 36 deletions

View File

@ -136,46 +136,86 @@ struct Constructor : public Expression {
return true;
}
template<typename type>
template <typename type>
type getVecComponent(int index) const {
SkASSERT(fType.kind() == Type::kVector_Kind);
if (fArguments.size() == 1 && fArguments[0]->fType.kind() == Type::kScalar_Kind) {
// This constructor just wraps a scalar. Propagate out the value.
if (std::is_floating_point<type>::value) {
return fArguments[0]->getConstantFloat();
} else {
return fArguments[0]->getConstantInt();
}
}
// Walk through all the constructor arguments until we reach the index we're searching for.
int current = 0;
for (const auto& arg : fArguments) {
SkASSERT(current <= index);
for (const std::unique_ptr<Expression>& arg : fArguments) {
if (current > index) {
// Somehow, we went past the argument we're looking for. Bail.
break;
}
if (arg->fType.kind() == Type::kScalar_Kind) {
if (index == current) {
// We're on the proper argument, and it's a scalar; fetch it.
if (std::is_floating_point<type>::value) {
return arg.get()->getConstantFloat();
return arg->getConstantFloat();
} else {
return arg.get()->getConstantInt();
return arg->getConstantInt();
}
}
current++;
} else if (arg->fKind == kConstructor_Kind) {
if (current + arg->fType.columns() > index) {
return ((const Constructor&) *arg).getVecComponent<type>(index - current);
}
current += arg->fType.columns();
} else {
if (current + arg->fType.columns() > index) {
SkASSERT(arg->fKind == kPrefix_Kind);
const PrefixExpression& p = (PrefixExpression&) *arg;
const Constructor& c = (const Constructor&) *p.fOperand;
return -c.getVecComponent<type>(index - current);
}
current += arg->fType.columns();
continue;
}
switch (arg->fKind) {
case kConstructor_Kind: {
const Constructor& constructor = static_cast<const Constructor&>(*arg);
if (current + constructor.fType.columns() > index) {
// We've found a constructor that overlaps the proper argument. Descend into
// it, honoring the type.
if (constructor.fType.componentType().isFloat()) {
return type(constructor.getVecComponent<SKSL_FLOAT>(index - current));
} else {
return type(constructor.getVecComponent<SKSL_INT>(index - current));
}
}
break;
}
case kPrefix_Kind: {
const PrefixExpression& prefix = static_cast<const PrefixExpression&>(*arg);
if (current + prefix.fType.columns() > index) {
// We found a prefix operator that contains the proper argument. Descend
// into it. We only support for constant propagation of the unary minus, so
// we shouldn't see any other tokens here.
SkASSERT(prefix.fOperator == Token::Kind::TK_MINUS);
// We expect the - prefix to always be attached to a constructor.
SkASSERT(prefix.fOperand->fKind == kConstructor_Kind);
const Constructor& constructor =
static_cast<const Constructor&>(*prefix.fOperand);
// Descend into this constructor, honoring the type.
if (constructor.fType.componentType().isFloat()) {
return -type(constructor.getVecComponent<SKSL_FLOAT>(index - current));
} else {
return -type(constructor.getVecComponent<SKSL_INT>(index - current));
}
}
break;
}
default: {
SkDEBUGFAILF("unexpected component %d { %s } in %s\n",
index, arg->description().c_str(), description().c_str());
break;
}
}
current += arg->fType.columns();
}
#ifdef SK_DEBUG
ABORT("failed to find vector component %d in %s\n", index, description().c_str());
#endif
SkDEBUGFAILF("failed to find vector component %d in %s\n", index, description().c_str());
return -1;
}

View File

@ -106,21 +106,21 @@ struct Swizzle : public Expression {
std::unique_ptr<Expression> constantPropagate(const IRGenerator& irGenerator,
const DefinitionMap& definitions) override {
if (fBase->fKind == Expression::kConstructor_Kind && fBase->isCompileTimeConstant()) {
// we're swizzling a constant vector, e.g. float4(1).x. Simplify it.
SkASSERT(fBase->fKind == Expression::kConstructor_Kind);
if (fType.isInteger()) {
SkASSERT(fComponents.size() == 1);
int64_t value = ((Constructor&) *fBase).getIVecComponent(fComponents[0]);
return std::unique_ptr<Expression>(new IntLiteral(irGenerator.fContext,
-1,
value));
} else if (fType.isFloat()) {
SkASSERT(fComponents.size() == 1);
double value = ((Constructor&) *fBase).getFVecComponent(fComponents[0]);
return std::unique_ptr<Expression>(new FloatLiteral(irGenerator.fContext,
-1,
value));
if (fBase->fKind == Expression::kConstructor_Kind) {
Constructor& constructor = static_cast<Constructor&>(*fBase);
if (constructor.isCompileTimeConstant()) {
// we're swizzling a constant vector, e.g. float4(1).x. Simplify it.
if (fType.isInteger()) {
SkASSERT(fComponents.size() == 1);
int64_t value = constructor.getIVecComponent(fComponents[0]);
return std::make_unique<IntLiteral>(irGenerator.fContext, constructor.fOffset,
value);
} else if (fType.isFloat()) {
SkASSERT(fComponents.size() == 1);
double value = constructor.getFVecComponent(fComponents[0]);
return std::make_unique<FloatLiteral>(irGenerator.fContext, constructor.fOffset,
value);
}
}
}
return nullptr;

View File

@ -2578,6 +2578,64 @@ DEF_TEST(SkSLSwizzleScalar, r) {
"}\n");
}
DEF_TEST(SkSLStackingVectorCasts, r) {
test(r,
"void main() {"
" if (half4(0, 0, 1, 1) == half4(int4(0, 0, 1, 1)))"
" sk_FragColor = half4(0, 1, 0, 1);"
" else"
" sk_FragColor = half4(1, 0, 0, 1);"
"}",
*SkSL::ShaderCapsFactory::Default(),
"#version 400\n"
"out vec4 sk_FragColor;\n"
"void main() {\n"
" sk_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
"}\n");
test(r,
"void main() {"
" if (half4(int4(0, 0, 1, 1)) == half4(int4(half4(0, 0, 1, 1))))"
" sk_FragColor = half4(0, 1, 0, 1);"
" else"
" sk_FragColor = half4(1, 0, 0, 1);"
"}",
*SkSL::ShaderCapsFactory::Default(),
"#version 400\n"
"out vec4 sk_FragColor;\n"
"void main() {\n"
" sk_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
"}\n");
}
DEF_TEST(SkSLCastsRoundTowardZero, r) {
test(r,
"void main() {"
" if (half4(int4(0, 0, 1, 2)) == half4(int4(half4(0.01, 0.99, 1.49, 2.75))))"
" sk_FragColor = half4(0, 1, 0, 1);"
" else"
" sk_FragColor = half4(1, 0, 0, 1);"
"}",
*SkSL::ShaderCapsFactory::Default(),
"#version 400\n"
"out vec4 sk_FragColor;\n"
"void main() {\n"
" sk_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
"}\n");
test(r,
"void main() {"
" if (half4(int4(0, 0, -1, -2)) == half4(int4(half4(-0.01, -0.99, -1.49, -2.75))))"
" sk_FragColor = half4(0, 1, 0, 1);"
" else"
" sk_FragColor = half4(1, 0, 0, 1);"
"}",
*SkSL::ShaderCapsFactory::Default(),
"#version 400\n"
"out vec4 sk_FragColor;\n"
"void main() {\n"
" sk_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
"}\n");
}
DEF_TEST(SkSLNegatedVectorLiteral, r) {
test(r,
"void main() {"