Fix codegen for integer vector-scalar arithmetic in SPIR-V.
Due to missing type-checks, we would emit `OpVectorTimesScalar` when multiplying an ivec with an int, or an `OpFDiv` when dividing an ivec against an int. Change-Id: Idc214dbe0ec208cb44f28b22e585584ac2ab7dae Bug: skia:11267, skia:11788 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/388742 Commit-Queue: John Stiles <johnstiles@google.com> Auto-Submit: John Stiles <johnstiles@google.com> Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
This commit is contained in:
parent
2febb5b423
commit
d94bfdd7d8
@ -2242,6 +2242,14 @@ static std::unique_ptr<Expression> create_literal_1(const Context& context, cons
|
||||
}
|
||||
}
|
||||
|
||||
SpvId SPIRVCodeGenerator::writeReciprocal(const Type& type, SpvId value, OutputStream& out) {
|
||||
SkASSERT(type.isFloat());
|
||||
SpvId one = this->writeFloatLiteral({/*offset=*/-1, /*value=*/1, &type});
|
||||
SpvId reciprocal = this->nextId(&type);
|
||||
this->writeInstruction(SpvOpFDiv, this->getType(type), reciprocal, one, value, out);
|
||||
return reciprocal;
|
||||
}
|
||||
|
||||
SpvId SPIRVCodeGenerator::writeBinaryExpression(const Type& leftType, SpvId lhs, Operator op,
|
||||
const Type& rightType, SpvId rhs,
|
||||
const Type& resultType, OutputStream& out) {
|
||||
@ -2255,18 +2263,21 @@ SpvId SPIRVCodeGenerator::writeBinaryExpression(const Type& leftType, SpvId lhs,
|
||||
// handling in SPIR-V
|
||||
if (this->getActualType(leftType) != this->getActualType(rightType)) {
|
||||
if (leftType.isVector() && rightType.isNumber()) {
|
||||
if (op.kind() == Token::Kind::TK_SLASH) {
|
||||
SpvId one = this->writeExpression(*create_literal_1(fContext, rightType), out);
|
||||
SpvId inverse = this->nextId(&rightType);
|
||||
this->writeInstruction(SpvOpFDiv, this->getType(rightType), inverse, one, rhs, out);
|
||||
rhs = inverse;
|
||||
op = Token::Kind::TK_STAR;
|
||||
}
|
||||
if (op.kind() == Token::Kind::TK_STAR) {
|
||||
SpvId result = this->nextId(&resultType);
|
||||
this->writeInstruction(SpvOpVectorTimesScalar, this->getType(resultType),
|
||||
result, lhs, rhs, out);
|
||||
return result;
|
||||
if (resultType.componentType().isFloat()) {
|
||||
switch (op.kind()) {
|
||||
case Token::Kind::TK_SLASH: {
|
||||
rhs = this->writeReciprocal(rightType, rhs, out);
|
||||
[[fallthrough]];
|
||||
}
|
||||
case Token::Kind::TK_STAR: {
|
||||
SpvId result = this->nextId(&resultType);
|
||||
this->writeInstruction(SpvOpVectorTimesScalar, this->getType(resultType),
|
||||
result, lhs, rhs, out);
|
||||
return result;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
// promote number to vector
|
||||
const Type& vecType = leftType;
|
||||
@ -2280,11 +2291,13 @@ SpvId SPIRVCodeGenerator::writeBinaryExpression(const Type& leftType, SpvId lhs,
|
||||
rhs = vec;
|
||||
operandType = &leftType;
|
||||
} else if (rightType.isVector() && leftType.isNumber()) {
|
||||
if (op.kind() == Token::Kind::TK_STAR) {
|
||||
SpvId result = this->nextId(&resultType);
|
||||
this->writeInstruction(SpvOpVectorTimesScalar, this->getType(resultType),
|
||||
result, rhs, lhs, out);
|
||||
return result;
|
||||
if (resultType.componentType().isFloat()) {
|
||||
if (op.kind() == Token::Kind::TK_STAR) {
|
||||
SpvId result = this->nextId(&resultType);
|
||||
this->writeInstruction(SpvOpVectorTimesScalar, this->getType(resultType),
|
||||
result, rhs, lhs, out);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
// promote number to vector
|
||||
const Type& vecType = rightType;
|
||||
|
@ -314,6 +314,8 @@ private:
|
||||
SpvId writeBinaryOperation(const BinaryExpression& expr, SpvOp_ ifFloat, SpvOp_ ifInt,
|
||||
SpvOp_ ifUInt, OutputStream& out);
|
||||
|
||||
SpvId writeReciprocal(const Type& type, SpvId value, OutputStream& out);
|
||||
|
||||
SpvId writeBinaryExpression(const Type& leftType, SpvId lhs, Operator op,
|
||||
const Type& rightType, SpvId rhs, const Type& resultType,
|
||||
OutputStream& out);
|
||||
|
@ -225,8 +225,7 @@ SKSL_TEST(SkSLTernaryExpression, "shared/TernaryExpression.sksl")
|
||||
SKSL_TEST(SkSLUnaryPositiveNegative, "shared/UnaryPositiveNegative.sksl")
|
||||
SKSL_TEST(SkSLUnusedVariables, "shared/UnusedVariables.sksl")
|
||||
SKSL_TEST(SkSLVectorConstructors, "shared/VectorConstructors.sksl")
|
||||
// TODO(skia:11267, skia:11788): Enable this test on GPU once SPIR-V vector/scalar int math is fixed
|
||||
SKSL_TEST_CPU(SkSLVectorScalarMath, "shared/VectorScalarMath.sksl")
|
||||
SKSL_TEST(SkSLVectorScalarMath, "shared/VectorScalarMath.sksl")
|
||||
|
||||
/*
|
||||
// Incompatible with Runtime Effects because calling a function before its definition is disallowed.
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user