Represent matrix casts with CompositeCast type.

Vector and matrix typecasting is mechanically very similar, so it makes
sense to represent these with a single constructor type and paper over
the tiny differences in each backend. (SPIR-V in particular needs a
separate path for matrix casting versus vector casting.)

Change-Id: Id9ea7ca6297e69b3e813c69bfdc56073b50d8d89
Bug: skia:11032
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/393216
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: John Stiles <johnstiles@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
This commit is contained in:
John Stiles 2021-04-07 12:30:22 -04:00 committed by Skia Commit-Bot
parent 75ee737770
commit 268a73f9e8
18 changed files with 120 additions and 127 deletions

View File

@ -98,6 +98,8 @@ skia_sksl_sources = [
"$_src/sksl/ir/SkSLConstructorArray.h",
"$_src/sksl/ir/SkSLConstructorComposite.cpp",
"$_src/sksl/ir/SkSLConstructorComposite.h",
"$_src/sksl/ir/SkSLConstructorCompositeCast.cpp",
"$_src/sksl/ir/SkSLConstructorCompositeCast.h",
"$_src/sksl/ir/SkSLConstructorDiagonalMatrix.cpp",
"$_src/sksl/ir/SkSLConstructorDiagonalMatrix.h",
"$_src/sksl/ir/SkSLConstructorMatrixResize.cpp",
@ -106,8 +108,6 @@ skia_sksl_sources = [
"$_src/sksl/ir/SkSLConstructorScalarCast.h",
"$_src/sksl/ir/SkSLConstructorSplat.cpp",
"$_src/sksl/ir/SkSLConstructorSplat.h",
"$_src/sksl/ir/SkSLConstructorVectorCast.cpp",
"$_src/sksl/ir/SkSLConstructorVectorCast.h",
"$_src/sksl/ir/SkSLContinueStatement.h",
"$_src/sksl/ir/SkSLDiscardStatement.h",
"$_src/sksl/ir/SkSLDoStatement.cpp",

View File

@ -749,11 +749,11 @@ bool Analysis::IsSameExpressionTree(const Expression& left, const Expression& ri
case Expression::Kind::kConstructor:
case Expression::Kind::kConstructorArray:
case Expression::Kind::kConstructorComposite:
case Expression::Kind::kConstructorCompositeCast:
case Expression::Kind::kConstructorDiagonalMatrix:
case Expression::Kind::kConstructorMatrixResize:
case Expression::Kind::kConstructorScalarCast:
case Expression::Kind::kConstructorSplat:
case Expression::Kind::kConstructorVectorCast: {
case Expression::Kind::kConstructorSplat: {
if (left.kind() != right.kind()) {
return false;
}
@ -1029,11 +1029,11 @@ public:
case Expression::Kind::kConstructor:
case Expression::Kind::kConstructorArray:
case Expression::Kind::kConstructorComposite:
case Expression::Kind::kConstructorCompositeCast:
case Expression::Kind::kConstructorDiagonalMatrix:
case Expression::Kind::kConstructorMatrixResize:
case Expression::Kind::kConstructorScalarCast:
case Expression::Kind::kConstructorSplat:
case Expression::Kind::kConstructorVectorCast:
case Expression::Kind::kFieldAccess:
case Expression::Kind::kIndex:
case Expression::Kind::kPrefix:
@ -1158,11 +1158,11 @@ template <typename T> bool TProgramVisitor<T>::visitExpression(typename T::Expre
case Expression::Kind::kConstructor:
case Expression::Kind::kConstructorArray:
case Expression::Kind::kConstructorComposite:
case Expression::Kind::kConstructorCompositeCast:
case Expression::Kind::kConstructorDiagonalMatrix:
case Expression::Kind::kConstructorMatrixResize:
case Expression::Kind::kConstructorScalarCast:
case Expression::Kind::kConstructorSplat:
case Expression::Kind::kConstructorVectorCast: {
case Expression::Kind::kConstructorSplat: {
auto& c = e.asAnyConstructor();
for (auto& arg : c.argumentSpan()) {
if (this->visitExpressionPtr(arg)) { return true; }

View File

@ -18,11 +18,11 @@
#include "src/sksl/ir/SkSLConstructor.h"
#include "src/sksl/ir/SkSLConstructorArray.h"
#include "src/sksl/ir/SkSLConstructorComposite.h"
#include "src/sksl/ir/SkSLConstructorCompositeCast.h"
#include "src/sksl/ir/SkSLConstructorDiagonalMatrix.h"
#include "src/sksl/ir/SkSLConstructorMatrixResize.h"
#include "src/sksl/ir/SkSLConstructorScalarCast.h"
#include "src/sksl/ir/SkSLConstructorSplat.h"
#include "src/sksl/ir/SkSLConstructorVectorCast.h"
#include "src/sksl/ir/SkSLContinueStatement.h"
#include "src/sksl/ir/SkSLDiscardStatement.h"
#include "src/sksl/ir/SkSLDoStatement.h"
@ -306,6 +306,12 @@ void Dehydrator::write(const Expression* e) {
this->writeExpressionSpan(e->as<ConstructorComposite>().argumentSpan());
break;
case Expression::Kind::kConstructorCompositeCast:
this->writeCommand(Rehydrator::kConstructorCompositeCast_Command);
this->write(e->type());
this->writeExpressionSpan(e->as<ConstructorCompositeCast>().argumentSpan());
break;
case Expression::Kind::kConstructorDiagonalMatrix:
this->writeCommand(Rehydrator::kConstructorDiagonalMatrix_Command);
this->write(e->type());
@ -330,12 +336,6 @@ void Dehydrator::write(const Expression* e) {
this->writeExpressionSpan(e->as<ConstructorSplat>().argumentSpan());
break;
case Expression::Kind::kConstructorVectorCast:
this->writeCommand(Rehydrator::kConstructorVectorCast_Command);
this->write(e->type());
this->writeExpressionSpan(e->as<ConstructorVectorCast>().argumentSpan());
break;
case Expression::Kind::kExternalFunctionCall:
case Expression::Kind::kExternalFunctionReference:
SkDEBUGFAIL("unimplemented--not expected to be used from within an include file");

View File

@ -205,7 +205,7 @@ void GLSLCodeGenerator::writeExpression(const Expression& expr, Precedence paren
this->writeAnyConstructor(expr.asAnyConstructor(), parentPrecedence);
break;
case Expression::Kind::kConstructorScalarCast:
case Expression::Kind::kConstructorVectorCast:
case Expression::Kind::kConstructorCompositeCast:
this->writeCastConstructor(expr.asAnyConstructor(), parentPrecedence);
break;
case Expression::Kind::kIntLiteral:

View File

@ -19,11 +19,11 @@
#include "src/sksl/ir/SkSLConstructor.h"
#include "src/sksl/ir/SkSLConstructorArray.h"
#include "src/sksl/ir/SkSLConstructorComposite.h"
#include "src/sksl/ir/SkSLConstructorCompositeCast.h"
#include "src/sksl/ir/SkSLConstructorDiagonalMatrix.h"
#include "src/sksl/ir/SkSLConstructorMatrixResize.h"
#include "src/sksl/ir/SkSLConstructorScalarCast.h"
#include "src/sksl/ir/SkSLConstructorSplat.h"
#include "src/sksl/ir/SkSLConstructorVectorCast.h"
#include "src/sksl/ir/SkSLContinueStatement.h"
#include "src/sksl/ir/SkSLDiscardStatement.h"
#include "src/sksl/ir/SkSLDoStatement.h"
@ -331,6 +331,12 @@ std::unique_ptr<Expression> Inliner::inlineExpression(int offset,
*ctor.type().clone(symbolTableForExpression),
argList(ctor.arguments()));
}
case Expression::Kind::kConstructorCompositeCast: {
const ConstructorCompositeCast& ctor = expression.as<ConstructorCompositeCast>();
return ConstructorCompositeCast::Make(*fContext, offset,
*ctor.type().clone(symbolTableForExpression),
expr(ctor.argument()));
}
case Expression::Kind::kConstructorDiagonalMatrix: {
const ConstructorDiagonalMatrix& ctor = expression.as<ConstructorDiagonalMatrix>();
return ConstructorDiagonalMatrix::Make(*fContext, offset,
@ -355,12 +361,6 @@ std::unique_ptr<Expression> Inliner::inlineExpression(int offset,
*ctor.type().clone(symbolTableForExpression),
expr(ctor.argument()));
}
case Expression::Kind::kConstructorVectorCast: {
const ConstructorVectorCast& ctor = expression.as<ConstructorVectorCast>();
return ConstructorVectorCast::Make(*fContext, offset,
*ctor.type().clone(symbolTableForExpression),
expr(ctor.argument()));
}
case Expression::Kind::kExternalFunctionCall: {
const ExternalFunctionCall& externalCall = expression.as<ExternalFunctionCall>();
return std::make_unique<ExternalFunctionCall>(offset, &externalCall.function(),
@ -958,11 +958,11 @@ public:
case Expression::Kind::kConstructor:
case Expression::Kind::kConstructorArray:
case Expression::Kind::kConstructorComposite:
case Expression::Kind::kConstructorCompositeCast:
case Expression::Kind::kConstructorDiagonalMatrix:
case Expression::Kind::kConstructorMatrixResize:
case Expression::Kind::kConstructorScalarCast:
case Expression::Kind::kConstructorSplat:
case Expression::Kind::kConstructorVectorCast: {
case Expression::Kind::kConstructorSplat: {
AnyConstructor& constructorExpr = (*expr)->asAnyConstructor();
for (std::unique_ptr<Expression>& arg : constructorExpr.argumentSpan()) {
this->visitExpression(&arg);

View File

@ -11,10 +11,10 @@
#include "src/sksl/SkSLCompiler.h"
#include "src/sksl/SkSLMemoryLayout.h"
#include "src/sksl/ir/SkSLConstructorArray.h"
#include "src/sksl/ir/SkSLConstructorCompositeCast.h"
#include "src/sksl/ir/SkSLConstructorDiagonalMatrix.h"
#include "src/sksl/ir/SkSLConstructorMatrixResize.h"
#include "src/sksl/ir/SkSLConstructorSplat.h"
#include "src/sksl/ir/SkSLConstructorVectorCast.h"
#include "src/sksl/ir/SkSLExpressionStatement.h"
#include "src/sksl/ir/SkSLExtension.h"
#include "src/sksl/ir/SkSLIndexExpression.h"
@ -189,7 +189,7 @@ void MetalCodeGenerator::writeExpression(const Expression& expr, Precedence pare
break;
case Expression::Kind::kConstructor:
case Expression::Kind::kConstructorScalarCast:
case Expression::Kind::kConstructorVectorCast:
case Expression::Kind::kConstructorCompositeCast:
this->writeCastConstructor(expr.asAnyConstructor(), "(", ")", parentPrecedence);
break;
case Expression::Kind::kIntLiteral:
@ -2277,11 +2277,11 @@ MetalCodeGenerator::Requirements MetalCodeGenerator::requirements(const Expressi
}
case Expression::Kind::kConstructor:
case Expression::Kind::kConstructorComposite:
case Expression::Kind::kConstructorCompositeCast:
case Expression::Kind::kConstructorArray:
case Expression::Kind::kConstructorDiagonalMatrix:
case Expression::Kind::kConstructorScalarCast:
case Expression::Kind::kConstructorSplat:
case Expression::Kind::kConstructorVectorCast: {
case Expression::Kind::kConstructorSplat: {
const AnyConstructor& c = e->asAnyConstructor();
Requirements result = kNo_Requirements;
for (const auto& arg : c.argumentSpan()) {

View File

@ -411,11 +411,11 @@ void PipelineStageCodeGenerator::writeExpression(const Expression& expr,
case Expression::Kind::kConstructor:
case Expression::Kind::kConstructorArray:
case Expression::Kind::kConstructorComposite:
case Expression::Kind::kConstructorCompositeCast:
case Expression::Kind::kConstructorDiagonalMatrix:
case Expression::Kind::kConstructorMatrixResize:
case Expression::Kind::kConstructorScalarCast:
case Expression::Kind::kConstructorSplat:
case Expression::Kind::kConstructorVectorCast:
this->writeAnyConstructor(expr.asAnyConstructor(), parentPrecedence);
break;
case Expression::Kind::kFieldAccess:

View File

@ -18,11 +18,11 @@
#include "src/sksl/ir/SkSLConstructor.h"
#include "src/sksl/ir/SkSLConstructorArray.h"
#include "src/sksl/ir/SkSLConstructorComposite.h"
#include "src/sksl/ir/SkSLConstructorCompositeCast.h"
#include "src/sksl/ir/SkSLConstructorDiagonalMatrix.h"
#include "src/sksl/ir/SkSLConstructorMatrixResize.h"
#include "src/sksl/ir/SkSLConstructorScalarCast.h"
#include "src/sksl/ir/SkSLConstructorSplat.h"
#include "src/sksl/ir/SkSLConstructorVectorCast.h"
#include "src/sksl/ir/SkSLContinueStatement.h"
#include "src/sksl/ir/SkSLDiscardStatement.h"
#include "src/sksl/ir/SkSLDoStatement.h"
@ -499,11 +499,12 @@ std::unique_ptr<Expression> Rehydrator::expression() {
SkASSERT(args.size() == 1);
return ConstructorSplat::Make(fContext, /*offset=*/-1, *type, std::move(args[0]));
}
case Rehydrator::kConstructorVectorCast_Command: {
case Rehydrator::kConstructorCompositeCast_Command: {
const Type* type = this->type();
ExpressionArray args = this->expressionArray();
SkASSERT(args.size() == 1);
return ConstructorVectorCast::Make(fContext, /*offset=*/-1, *type, std::move(args[0]));
return ConstructorCompositeCast::Make(fContext, /*offset=*/-1, *type,
std::move(args[0]));
}
case Rehydrator::kFieldAccess_Command: {
std::unique_ptr<Expression> base = this->expression();

View File

@ -53,11 +53,11 @@ public:
kConstructor_Command,
kConstructorArray_Command,
kConstructorComposite_Command,
kConstructorCompositeCast_Command,
kConstructorDiagonalMatrix_Command,
kConstructorMatrixResize_Command,
kConstructorScalarCast_Command,
kConstructorSplat_Command,
kConstructorVectorCast_Command,
kConstructorReserved4_Command,
kConstructorReserved5_Command,
kContinue_Command,

View File

@ -723,8 +723,8 @@ SpvId SPIRVCodeGenerator::writeExpression(const Expression& expr, OutputStream&
return this->writeConstructorSplat(expr.as<ConstructorSplat>(), out);
case Expression::Kind::kConstructorComposite:
return this->writeConstructorComposite(expr.as<ConstructorComposite>(), out);
case Expression::Kind::kConstructorVectorCast:
return this->writeConstructorVectorCast(expr.as<ConstructorVectorCast>(), out);
case Expression::Kind::kConstructorCompositeCast:
return this->writeConstructorCompositeCast(expr.as<ConstructorCompositeCast>(), out);
case Expression::Kind::kIntLiteral:
return this->writeIntLiteral(expr.as<IntLiteral>());
case Expression::Kind::kFieldAccess:
@ -1415,11 +1415,12 @@ void SPIRVCodeGenerator::writeUniformScaleMatrix(SpvId id, SpvId diagonal, const
}
}
void SPIRVCodeGenerator::writeMatrixCopy(SpvId id, SpvId src, const Type& srcType,
const Type& dstType, OutputStream& out) {
SpvId SPIRVCodeGenerator::writeMatrixCopy(SpvId src, const Type& srcType, const Type& dstType,
OutputStream& out) {
SkASSERT(srcType.isMatrix());
SkASSERT(dstType.isMatrix());
SkASSERT(srcType.componentType() == dstType.componentType());
SpvId id = this->nextId(&dstType);
SpvId srcColumnType = this->getType(srcType.componentType().toCompound(fContext,
srcType.rows(),
1));
@ -1486,6 +1487,7 @@ void SPIRVCodeGenerator::writeMatrixCopy(SpvId id, SpvId src, const Type& srcTyp
for (int i = 0; i < dstType.columns(); i++) {
this->writeWord(columns[i], out);
}
return id;
}
void SPIRVCodeGenerator::addColumnEntry(SpvId columnType, Precision precision,
@ -1525,9 +1527,8 @@ SpvId SPIRVCodeGenerator::writeMatrixConstructor(const ConstructorComposite& c,
SpvId result = this->nextId(&type);
int rows = type.rows();
int columns = type.columns();
if (arguments.size() == 1 && arg0Type.isMatrix()) {
this->writeMatrixCopy(result, arguments[0], arg0Type, type, out);
} else if (arguments.size() == 1 && arg0Type.isVector()) {
if (arguments.size() == 1 && arg0Type.isVector()) {
// Special-case handling of float4 -> mat2x2.
SkASSERT(type.rows() == 2 && type.columns() == 2);
SkASSERT(arg0Type.columns() == 4);
SpvId componentType = this->getType(type.componentType());
@ -1666,11 +1667,6 @@ SpvId SPIRVCodeGenerator::writeArrayConstructor(const ConstructorArray& c, Outpu
}
SpvId SPIRVCodeGenerator::writeConstructor(const Constructor& c, OutputStream& out) {
const Type& type = c.type();
if (c.arguments().size() == 1 &&
this->getActualType(type) == this->getActualType(c.arguments()[0]->type())) {
return this->writeExpression(*c.arguments()[0], out);
}
fErrors.error(c.fOffset, "unsupported constructor: " + c.description());
return -1;
}
@ -1687,16 +1683,21 @@ SpvId SPIRVCodeGenerator::writeConstructorScalarCast(const ConstructorScalarCast
return this->castScalarToType(expressionId, ctorExpr.type(), type, out);
}
SpvId SPIRVCodeGenerator::writeConstructorVectorCast(const ConstructorVectorCast& c,
OutputStream& out) {
SpvId SPIRVCodeGenerator::writeConstructorCompositeCast(const ConstructorCompositeCast& c,
OutputStream& out) {
const Type& ctorType = c.type();
const Type& argType = c.argument()->type();
SkASSERT(ctorType.isVector());
SkASSERT(ctorType.isVector() || ctorType.isMatrix());
// Write the vector that we are casting. If the actual type matches, we are done.
SpvId vectorId = this->writeExpression(*c.argument(), out);
// Write the composite that we are casting. If the actual type matches, we are done.
SpvId compositeId = this->writeExpression(*c.argument(), out);
if (this->getActualType(ctorType) == this->getActualType(argType)) {
return vectorId;
return compositeId;
}
// writeMatrixCopy can cast matrices to a different type.
if (ctorType.isMatrix()) {
return this->writeMatrixCopy(compositeId, argType, ctorType, out);
}
// SPIR-V doesn't support vector(vector-of-different-type) directly, so we need to extract the
@ -1705,10 +1706,11 @@ SpvId SPIRVCodeGenerator::writeConstructorVectorCast(const ConstructorVectorCast
const Type& dstType = ctorType.componentType();
std::vector<SpvId> arguments;
arguments.reserve(argType.columns());
for (int index = 0; index < argType.columns(); ++index) {
SpvId componentId = this->nextId(&srcType);
this->writeInstruction(SpvOpCompositeExtract, this->getType(srcType), componentId,
vectorId, index, out);
compositeId, index, out);
arguments.push_back(this->castScalarToType(componentId, srcType, dstType, out));
}
@ -1736,10 +1738,7 @@ SpvId SPIRVCodeGenerator::writeConstructorMatrixResize(const ConstructorMatrixRe
SpvId argument = this->writeExpression(*c.argument(), out);
// Use matrix-copy to resize the input matrix to its new size.
const Type& type = c.type();
SpvId result = this->nextId(&type);
this->writeMatrixCopy(result, argument, c.argument()->type(), type, out);
return result;
return this->writeMatrixCopy(argument, c.argument()->type(), c.type(), out);
}
static SpvStorageClass_ get_storage_class(const Variable& var,

View File

@ -24,11 +24,11 @@
#include "src/sksl/ir/SkSLConstructor.h"
#include "src/sksl/ir/SkSLConstructorArray.h"
#include "src/sksl/ir/SkSLConstructorComposite.h"
#include "src/sksl/ir/SkSLConstructorCompositeCast.h"
#include "src/sksl/ir/SkSLConstructorDiagonalMatrix.h"
#include "src/sksl/ir/SkSLConstructorMatrixResize.h"
#include "src/sksl/ir/SkSLConstructorScalarCast.h"
#include "src/sksl/ir/SkSLConstructorSplat.h"
#include "src/sksl/ir/SkSLConstructorVectorCast.h"
#include "src/sksl/ir/SkSLDoStatement.h"
#include "src/sksl/ir/SkSLFieldAccess.h"
#include "src/sksl/ir/SkSLFloatLiteral.h"
@ -282,8 +282,7 @@ private:
* source matrix are filled with zero; entries which do not exist in the destination matrix are
* ignored.
*/
void writeMatrixCopy(SpvId id, SpvId src, const Type& srcType, const Type& dstType,
OutputStream& out);
SpvId writeMatrixCopy(SpvId src, const Type& srcType, const Type& dstType, OutputStream& out);
void addColumnEntry(SpvId columnType, Precision precision, std::vector<SpvId>* currentColumn,
std::vector<SpvId>* columnIds, int* currentCount, int rows, SpvId entry,
@ -307,7 +306,7 @@ private:
SpvId writeConstructorSplat(const ConstructorSplat& c, OutputStream& out);
SpvId writeConstructorVectorCast(const ConstructorVectorCast& c, OutputStream& out);
SpvId writeConstructorCompositeCast(const ConstructorCompositeCast& c, OutputStream& out);
SpvId writeComposite(const std::vector<SpvId>& arguments, const Type& type, OutputStream& out);

View File

@ -646,29 +646,6 @@ Value SkVMGenerator::writeAggregationConstructor(const AnyConstructor& c) {
}
Value SkVMGenerator::writeConstructor(const Constructor& c) {
if (c.arguments().size() > 1) {
// Multi-argument constructors just aggregate their arguments, with no conversion
// NOTE: This (SkSL rule) is actually more restrictive than GLSL.
return this->writeAggregationConstructor(c);
}
const Type& srcType = c.arguments()[0]->type();
const Type& dstType = c.type();
Type::NumberKind srcKind = base_number_kind(srcType),
dstKind = base_number_kind(dstType);
Value src = this->writeExpression(*c.arguments()[0]);
size_t dstSlots = dstType.slotCount();
// Conversion among "similar" types (floatN <-> halfN), (shortN <-> intN), etc. is a no-op
if (srcKind == dstKind && src.slots() == dstSlots) {
return src;
}
if (srcKind != dstKind) {
// One argument constructors can do type conversion
return this->writeTypeConversion(src, srcKind, dstKind);
}
SkDEBUGFAIL("Invalid constructor");
return {};
}
@ -1472,7 +1449,7 @@ Value SkVMGenerator::writeExpression(const Expression& e) {
case Expression::Kind::kConstructorMatrixResize:
return this->writeConstructorMatrixResize(e.as<ConstructorMatrixResize>());
case Expression::Kind::kConstructorScalarCast:
case Expression::Kind::kConstructorVectorCast:
case Expression::Kind::kConstructorCompositeCast:
return this->writeConstructorCast(e.asAnyConstructor());
case Expression::Kind::kConstructorSplat:
return this->writeConstructorSplat(e.as<ConstructorSplat>());

View File

@ -3899,7 +3899,7 @@ static uint8_t SKSL_INCLUDE_sksl_gpu[] = {8,10,
2,
51,0,0,0,0,1,
43,
12,
13,
49,15,2,1,
28,
49,176,0,0,0,0,0,1,0,
@ -3948,11 +3948,11 @@ static uint8_t SKSL_INCLUDE_sksl_gpu[] = {8,10,
53,
1,
58,167,3,0,66,
12,
13,
49,15,2,1,
28,
49,176,0,0,0,0,0,
12,
13,
49,15,2,1,
28,
49,176,0,0,0,0,0,
@ -5115,7 +5115,7 @@ static uint8_t SKSL_INCLUDE_sksl_gpu[] = {8,10,
2,
51,0,0,0,0,1,
43,
12,
13,
49,172,1,1,
28,
49,176,0,0,0,0,0,1,1,1,211,3,
@ -5823,7 +5823,7 @@ static uint8_t SKSL_INCLUDE_sksl_gpu[] = {8,10,
58,18,4,0,
59,
43,
12,
13,
49,15,2,1,
28,
49,176,0,0,0,0,0,1,29,154,3,157,3,160,3,163,3,166,3,169,3,172,3,175,3,178,3,181,3,184,3,187,3,190,3,193,3,196,3,202,3,205,3,208,3,221,3,227,3,230,3,236,3,239,3,242,3,245,3,6,4,9,4,12,4,15,4,

View File

@ -10,11 +10,11 @@
#include "src/sksl/ir/SkSLBoolLiteral.h"
#include "src/sksl/ir/SkSLConstructorArray.h"
#include "src/sksl/ir/SkSLConstructorComposite.h"
#include "src/sksl/ir/SkSLConstructorCompositeCast.h"
#include "src/sksl/ir/SkSLConstructorDiagonalMatrix.h"
#include "src/sksl/ir/SkSLConstructorMatrixResize.h"
#include "src/sksl/ir/SkSLConstructorScalarCast.h"
#include "src/sksl/ir/SkSLConstructorSplat.h"
#include "src/sksl/ir/SkSLConstructorVectorCast.h"
#include "src/sksl/ir/SkSLFloatLiteral.h"
#include "src/sksl/ir/SkSLIntLiteral.h"
#include "src/sksl/ir/SkSLPrefixExpression.h"
@ -71,28 +71,24 @@ std::unique_ptr<Expression> Constructor::MakeCompoundConstructor(const Context&
// A vector constructor containing a single vector with the same number of columns is a
// cast (e.g. float3 -> int3).
if (type.isVector() && argument->type().columns() == type.columns()) {
return ConstructorVectorCast::Make(context, offset, type, std::move(argument));
return ConstructorCompositeCast::Make(context, offset, type, std::move(argument));
}
} else if (argument->type().isMatrix()) {
// A matrix constructor containing a single matrix can be a resize, typecast, or both.
// GLSL lumps these into one category, but internally SkSL keeps them distinct.
if (type.isMatrix()) {
// First, handle type conversion. If the component types differ, synthesize the
// destination type with the argument's rows/columns. If not, leave it as-is.
std::unique_ptr<Expression> typecast;
if (type.componentType() != argument->type().componentType()) {
const Type& typecastType = type.componentType().toCompound(
context,
argument->type().columns(),
argument->type().rows());
typecast = std::make_unique<Constructor>(offset, typecastType, std::move(args));
SkASSERT(typecast);
} else {
typecast = std::move(argument);
}
// destination type with the argument's rows/columns. (This will be a no-op if it's
// already the right type.)
const Type& typecastType = type.componentType().toCompound(
context,
argument->type().columns(),
argument->type().rows());
std::unique_ptr<Expression> typecast = ConstructorCompositeCast::Make(
context, offset, typecastType, std::move(argument));
// Next, wrap the typecasted expression in a matrix-resize constructor if the sizes
// differ. If not, return the typecasted expression as-is.
// Next, wrap the typecasted expression in a matrix-resize constructor if the
// sizes differ. (This will be a no-op if it's already the right size.)
return ConstructorMatrixResize::Make(context, offset, type, std::move(typecast));
}
}

View File

@ -188,6 +188,11 @@ public:
}
private:
static std::unique_ptr<Expression> MakeScalarConstructor(const Context& context,
int offset,
const Type& type,
ExpressionArray args);
static std::unique_ptr<Expression> MakeCompoundConstructor(const Context& context,
int offset,
const Type& type,

View File

@ -5,21 +5,22 @@
* found in the LICENSE file.
*/
#include "src/sksl/ir/SkSLConstructorVectorCast.h"
#include "src/sksl/ir/SkSLConstructorCompositeCast.h"
#include "src/sksl/ir/SkSLConstructor.h"
#include "src/sksl/ir/SkSLConstructorComposite.h"
#include "src/sksl/ir/SkSLConstructorDiagonalMatrix.h"
#include "src/sksl/ir/SkSLConstructorScalarCast.h"
#include "src/sksl/ir/SkSLConstructorSplat.h"
namespace SkSL {
static std::unique_ptr<Expression> cast_constant_vector(const Context& context,
const Type& destType,
std::unique_ptr<Expression> constCtor) {
static std::unique_ptr<Expression> cast_constant_composite(const Context& context,
const Type& destType,
std::unique_ptr<Expression> constCtor) {
const Type& scalarType = destType.componentType();
if (constCtor->is<ConstructorSplat>()) {
// This is a vector-cast of a splat containing a constant value, e.g. `half4(7)`. We can
// This is a composite-cast of a splat containing a constant value, e.g. `half4(7)`. We can
// replace it with a splat of a different type, e.g. `int4(7)`.
ConstructorSplat& splat = constCtor->as<ConstructorSplat>();
return ConstructorSplat::Make(
@ -28,6 +29,16 @@ static std::unique_ptr<Expression> cast_constant_vector(const Context& context,
std::move(splat.argument())));
}
if (constCtor->is<ConstructorDiagonalMatrix>()) {
// This is a composite-cast of a diagonal matrix, e.g. `float3x3(2)`. We can
// replace it with a splat of a different type, e.g. `half3x3(2)`.
ConstructorDiagonalMatrix& splat = constCtor->as<ConstructorDiagonalMatrix>();
return ConstructorDiagonalMatrix::Make(
context, constCtor->fOffset, destType,
ConstructorScalarCast::Make(context, constCtor->fOffset, scalarType,
std::move(splat.argument())));
}
// Create a composite Constructor(literal, ...) which typecasts each argument inside.
auto inputArgs = constCtor->asAnyConstructor().argumentSpan();
ExpressionArray typecastArgs;
@ -39,9 +50,9 @@ static std::unique_ptr<Expression> cast_constant_vector(const Context& context,
typecastArgs.push_back(ConstructorScalarCast::Make(context, offset, scalarType,
std::move(arg)));
} else {
// Convert inner constant-vectors recursively.
// Convert inner constant-composites recursively.
SkASSERT(argType.isVector());
typecastArgs.push_back(cast_constant_vector(
typecastArgs.push_back(cast_constant_composite(
context,
scalarType.toCompound(context, /*columns=*/argType.columns(), /*rows=*/1),
std::move(arg)));
@ -52,14 +63,16 @@ static std::unique_ptr<Expression> cast_constant_vector(const Context& context,
std::move(typecastArgs));
}
std::unique_ptr<Expression> ConstructorVectorCast::Make(const Context& context,
std::unique_ptr<Expression> ConstructorCompositeCast::Make(const Context& context,
int offset,
const Type& type,
std::unique_ptr<Expression> arg) {
// The types must both be vectors of the same size.
SkASSERT(type.isVector());
SkASSERT(arg->type().isVector());
// Only vectors or matrices of the same dimensions are allowed.
SkASSERT(type.isVector() || type.isMatrix());
SkASSERT(arg->type().isVector() == type.isVector());
SkASSERT(arg->type().isMatrix() == type.isMatrix());
SkASSERT(type.columns() == arg->type().columns());
SkASSERT(type.rows() == arg->type().rows());
// If this is a no-op cast, return the expression as-is.
if (type == arg->type()) {
@ -67,9 +80,9 @@ std::unique_ptr<Expression> ConstructorVectorCast::Make(const Context& context,
}
// We can cast a vector of compile-time constants at compile-time.
if (arg->isCompileTimeConstant()) {
return cast_constant_vector(context, type, std::move(arg));
return cast_constant_composite(context, type, std::move(arg));
}
return std::make_unique<ConstructorVectorCast>(offset, type, std::move(arg));
return std::make_unique<ConstructorCompositeCast>(offset, type, std::move(arg));
}
} // namespace SkSL

View File

@ -17,15 +17,16 @@
namespace SkSL {
/**
* Represents the construction of a vector cast, such as `half3(myInt3)`.
* Represents the construction of a vector/matrix typecast, such as `half3(myInt3)` or
* `float4x4(myHalf4x4)`. Matrix resizes are done in ConstructorMatrixResize, not here.
*
* These always contain exactly 1 vector of matching size, and are never constant.
* These always contain exactly 1 vector or matrix of matching size, and are never constant.
*/
class ConstructorVectorCast final : public SingleArgumentConstructor {
class ConstructorCompositeCast final : public SingleArgumentConstructor {
public:
static constexpr Kind kExpressionKind = Kind::kConstructorVectorCast;
static constexpr Kind kExpressionKind = Kind::kConstructorCompositeCast;
ConstructorVectorCast(int offset, const Type& type, std::unique_ptr<Expression> arg)
ConstructorCompositeCast(int offset, const Type& type, std::unique_ptr<Expression> arg)
: INHERITED(offset, kExpressionKind, &type, std::move(arg)) {}
static std::unique_ptr<Expression> Make(const Context& context,
@ -39,7 +40,8 @@ public:
}
std::unique_ptr<Expression> clone() const override {
return std::make_unique<ConstructorVectorCast>(fOffset, this->type(), argument()->clone());
return std::make_unique<ConstructorCompositeCast>(fOffset, this->type(),
argument()->clone());
}
private:

View File

@ -33,11 +33,11 @@ public:
kConstructor,
kConstructorArray,
kConstructorComposite,
kConstructorCompositeCast,
kConstructorDiagonalMatrix,
kConstructorMatrixResize,
kConstructorScalarCast,
kConstructorSplat,
kConstructorVectorCast,
kDefined,
kExternalFunctionCall,
kExternalFunctionReference,
@ -88,8 +88,9 @@ public:
}
bool isAnyConstructor() const {
static_assert((int)Kind::kConstructorVectorCast + 1 == (int)Kind::kDefined);
return this->kind() >= Kind::kConstructor && this->kind() <= Kind::kConstructorVectorCast;
static_assert((int)Kind::kConstructor - 1 == (int)Kind::kCodeString);
static_assert((int)Kind::kConstructorSplat + 1 == (int)Kind::kDefined);
return this->kind() >= Kind::kConstructor && this->kind() <= Kind::kConstructorSplat;
}
/**