fixed SkSL handling of negated literal vectors

Bug: oss-fuzz:14409
Change-Id: I837083139489d46f7db2f697ce85a0cabf85fb94
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/219997
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
This commit is contained in:
Ethan Nicholas 2019-06-10 15:55:38 -04:00 committed by Skia Commit-Bot
parent 6488077ea3
commit d188c18835
6 changed files with 67 additions and 18 deletions

View File

@ -535,9 +535,15 @@ bool is_constant(const Expression& expr, double value) {
return ((FloatLiteral&) expr).fValue == value;
case Expression::kConstructor_Kind: {
Constructor& c = (Constructor&) expr;
bool isFloat = c.fType.columns() > 1 ? c.fType.componentType().isFloat()
: c.fType.isFloat();
if (c.fType.kind() == Type::kVector_Kind && c.isConstant()) {
for (int i = 0; i < c.fType.columns(); ++i) {
if (!is_constant(*c.getVecComponent(i), value)) {
if (isFloat) {
if (c.getFVecComponent(i) != value) {
return false;
}
} else if (c.getIVecComponent(i) != value) {
return false;
}
}

View File

@ -23,7 +23,7 @@
#endif // SK_SUPPORT_GPU
#endif // SKSL_STANDALONE
using SKSL_INT = uint32_t;
using SKSL_INT = int32_t;
using SKSL_FLOAT = float;
class GrShaderCaps;

View File

@ -92,8 +92,14 @@ struct Constructor : public Expression {
SkASSERT(other.fKind == Expression::kConstructor_Kind && other.fType == fType);
Constructor& c = (Constructor&) other;
if (c.fType.kind() == Type::kVector_Kind) {
bool isFloat = c.fType.columns() > 1 ? c.fType.componentType().isFloat()
: c.fType.isFloat();
for (int i = 0; i < fType.columns(); i++) {
if (!this->getVecComponent(i)->compareConstant(context, *c.getVecComponent(i))) {
if (isFloat) {
if (this->getFVecComponent(i) != c.getFVecComponent(i)) {
return false;
}
} else if (this->getIVecComponent(i) != c.getIVecComponent(i)) {
return false;
}
}
@ -113,22 +119,39 @@ struct Constructor : public Expression {
return true;
}
const Expression* getVecComponent(int index) const {
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) {
return fArguments[0].get();
if (std::is_floating_point<type>::value) {
return fArguments[0]->getConstantFloat();
} else {
return fArguments[0]->getConstantInt();
}
}
int current = 0;
for (const auto& arg : fArguments) {
SkASSERT(current <= index);
if (arg->fType.kind() == Type::kScalar_Kind) {
if (index == current) {
return arg.get();
if (std::is_floating_point<type>::value) {
return arg.get()->getConstantFloat();
} else {
return arg.get()->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) {
return ((const Constructor&) *arg).getVecComponent(index - current);
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();
}
@ -136,15 +159,19 @@ struct Constructor : public Expression {
ABORT("failed to find vector component %d in %s\n", index, description().c_str());
}
double getFVecComponent(int index) const override {
return this->getVecComponent(index)->getConstantFloat();
SKSL_FLOAT getFVecComponent(int n) const override {
return this->getVecComponent<SKSL_FLOAT>(n);
}
int64_t getIVecComponent(int index) const override {
return this->getVecComponent(index)->getConstantInt();
/**
* For a literal vector expression, return the integer value of the n'th vector component. It is
* an error to call this method on an expression which is not a literal vector.
*/
SKSL_INT getIVecComponent(int n) const override {
return this->getVecComponent<SKSL_INT>(n);
}
double getMatComponent(int col, int row) const override {
SKSL_FLOAT getMatComponent(int col, int row) const override {
SkASSERT(this->isConstant());
SkASSERT(fType.kind() == Type::kMatrix_Kind);
SkASSERT(col < fType.columns() && row < fType.rows());

View File

@ -113,7 +113,7 @@ struct Expression : public IRNode {
* For a literal vector expression, return the floating point value of the n'th vector
* component. It is an error to call this method on an expression which is not a literal vector.
*/
virtual double getFVecComponent(int n) const {
virtual SKSL_FLOAT getFVecComponent(int n) const {
SkASSERT(false);
return 0;
}
@ -122,7 +122,7 @@ struct Expression : public IRNode {
* For a literal vector expression, return the integer value of the n'th vector component. It is
* an error to call this method on an expression which is not a literal vector.
*/
virtual int64_t getIVecComponent(int n) const {
virtual SKSL_INT getIVecComponent(int n) const {
SkASSERT(false);
return 0;
}
@ -132,7 +132,7 @@ struct Expression : public IRNode {
* [col][row]. It is an error to call this method on an expression which is not a literal
* matrix.
*/
virtual double getMatComponent(int col, int row) const {
virtual SKSL_FLOAT getMatComponent(int col, int row) const {
SkASSERT(false);
return 0;
}

View File

@ -46,17 +46,17 @@ struct PrefixExpression : public Expression {
return nullptr;
}
double getFVecComponent(int index) const override {
SKSL_FLOAT getFVecComponent(int index) const override {
SkASSERT(fOperator == Token::Kind::MINUS);
return -fOperand->getFVecComponent(index);
}
int64_t getIVecComponent(int index) const override {
SKSL_INT getIVecComponent(int index) const override {
SkASSERT(fOperator == Token::Kind::MINUS);
return -fOperand->getIVecComponent(index);
}
double getMatComponent(int col, int row) const override {
SKSL_FLOAT getMatComponent(int col, int row) const override {
SkASSERT(fOperator == Token::Kind::MINUS);
return -fOperand->getMatComponent(col, row);
}

View File

@ -2296,3 +2296,19 @@ DEF_TEST(SkSLSwizzleConstants, r) {
SkSL::Program::kFragment_Kind
);
}
DEF_TEST(SkSLNegatedVectorLiteral, r) {
test(r,
"void main() {"
" if (half4(1) == half4(-half2(-1), half2(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");
}