Implement array casts in Metal.
These are not very interesting right now, because the in and out types boil down to the same thing (int/int, float/float). When half- precision types are enabled, these helpers will be more useful. They will return an array which casts each element from int-to-short or float-to-half (or vice versa). Change-Id: Ida716ddd27d370ba33fd23f17a1b07fa5a201e40 Bug: skia:12339 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/463337 Commit-Queue: John Stiles <johnstiles@google.com> Reviewed-by: Brian Osman <brianosman@google.com>
This commit is contained in:
parent
2a372177e8
commit
8ed23eb917
@ -148,7 +148,7 @@ void MetalCodeGenerator::writeExpression(const Expression& expr, Precedence pare
|
||||
this->writeAnyConstructor(expr.asAnyConstructor(), "{", "}", parentPrecedence);
|
||||
break;
|
||||
case Expression::Kind::kConstructorArrayCast:
|
||||
this->writeExpression(*expr.as<ConstructorArrayCast>().argument(), parentPrecedence);
|
||||
this->writeConstructorArrayCast(expr.as<ConstructorArrayCast>(), parentPrecedence);
|
||||
break;
|
||||
case Expression::Kind::kConstructorCompound:
|
||||
this->writeConstructorCompound(expr.as<ConstructorCompound>(), parentPrecedence);
|
||||
@ -1157,6 +1157,37 @@ void MetalCodeGenerator::writeConstructorCompound(const ConstructorCompound& c,
|
||||
}
|
||||
}
|
||||
|
||||
void MetalCodeGenerator::writeConstructorArrayCast(const ConstructorArrayCast& c,
|
||||
Precedence parentPrecedence) {
|
||||
const Type& inType = c.argument()->type().componentType();
|
||||
const Type& outType = c.type().componentType();
|
||||
String inTypeName = this->typeName(inType);
|
||||
String outTypeName = this->typeName(outType);
|
||||
|
||||
String name = "array_of_" + outTypeName + "_from_" + inTypeName;
|
||||
auto [iter, didInsert] = fHelpers.insert(name);
|
||||
if (didInsert) {
|
||||
fExtraFunctions.printf(R"(
|
||||
template <size_t N>
|
||||
array<%s, N> %s(thread const array<%s, N>& x) {
|
||||
array<%s, N> result;
|
||||
for (int i = 0; i < N; ++i) {
|
||||
result[i] = %s(x[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
)",
|
||||
outTypeName.c_str(), name.c_str(), inTypeName.c_str(),
|
||||
outTypeName.c_str(),
|
||||
outTypeName.c_str());
|
||||
}
|
||||
|
||||
this->write(name);
|
||||
this->write("(");
|
||||
this->writeExpression(*c.argument(), Precedence::kSequence);
|
||||
this->write(")");
|
||||
}
|
||||
|
||||
String MetalCodeGenerator::getVectorFromMat2x2ConstructorHelper(const Type& matrixType) {
|
||||
SkASSERT(matrixType.isMatrix());
|
||||
SkASSERT(matrixType.rows() == 2);
|
||||
|
@ -19,6 +19,7 @@ namespace SkSL {
|
||||
|
||||
class BinaryExpression;
|
||||
class Block;
|
||||
class ConstructorArrayCast;
|
||||
class ConstructorCompound;
|
||||
class ConstructorMatrixResize;
|
||||
class DoStatement;
|
||||
@ -210,6 +211,8 @@ protected:
|
||||
const char* rightBracket,
|
||||
Precedence parentPrecedence);
|
||||
|
||||
void writeConstructorArrayCast(const ConstructorArrayCast& c, Precedence parentPrecedence);
|
||||
|
||||
void writeFieldAccess(const FieldAccess& f);
|
||||
|
||||
void writeSwizzle(const Swizzle& swizzle);
|
||||
|
@ -19,6 +19,33 @@ bool operator!=(thread const array<T1, N>& left, thread const array<T2, N>& righ
|
||||
thread bool operator==(const float2x2 left, const float2x2 right);
|
||||
thread bool operator!=(const float2x2 left, const float2x2 right);
|
||||
|
||||
template <size_t N>
|
||||
array<float, N> array_of_float_from_float(thread const array<float, N>& x) {
|
||||
array<float, N> result;
|
||||
for (int i = 0; i < N; ++i) {
|
||||
result[i] = float(x[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
array<int3, N> array_of_int3_from_int3(thread const array<int3, N>& x) {
|
||||
array<int3, N> result;
|
||||
for (int i = 0; i < N; ++i) {
|
||||
result[i] = int3(x[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
array<float2x2, N> array_of_float2x2_from_float2x2(thread const array<float2x2, N>& x) {
|
||||
array<float2x2, N> result;
|
||||
for (int i = 0; i < N; ++i) {
|
||||
result[i] = float2x2(x[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, size_t N>
|
||||
bool operator==(thread const array<T1, N>& left, thread const array<T2, N>& right) {
|
||||
for (size_t index = 0; index < N; ++index) {
|
||||
@ -44,17 +71,17 @@ fragment Outputs fragmentMain(Inputs _in [[stage_in]], constant Uniforms& _unifo
|
||||
Outputs _out;
|
||||
(void)_out;
|
||||
array<float, 4> f = array<float, 4>{1.0, 2.0, 3.0, 4.0};
|
||||
array<float, 4> h = f;
|
||||
f = h;
|
||||
h = f;
|
||||
array<float, 4> h = array_of_float_from_float(f);
|
||||
f = array_of_float_from_float(h);
|
||||
h = array_of_float_from_float(f);
|
||||
array<int3, 3> i3 = array<int3, 3>{int3(1), int3(2), int3(3)};
|
||||
array<int3, 3> s3 = i3;
|
||||
i3 = s3;
|
||||
s3 = i3;
|
||||
array<int3, 3> s3 = array_of_int3_from_int3(i3);
|
||||
i3 = array_of_int3_from_int3(s3);
|
||||
s3 = array_of_int3_from_int3(i3);
|
||||
array<float2x2, 2> h2x2 = array<float2x2, 2>{float2x2(float2(1.0, 2.0), float2(3.0, 4.0)), float2x2(float2(5.0, 6.0), float2(7.0, 8.0))};
|
||||
array<float2x2, 2> f2x2 = h2x2;
|
||||
f2x2 = h2x2;
|
||||
h2x2 = f2x2;
|
||||
_out.sk_FragColor = (f == h && i3 == s3) && f2x2 == h2x2 ? _uniforms.colorGreen : _uniforms.colorRed;
|
||||
array<float2x2, 2> f2x2 = array_of_float2x2_from_float2x2(h2x2);
|
||||
f2x2 = array_of_float2x2_from_float2x2(h2x2);
|
||||
h2x2 = array_of_float2x2_from_float2x2(f2x2);
|
||||
_out.sk_FragColor = (f == array_of_float_from_float(h) && i3 == array_of_int3_from_int3(s3)) && f2x2 == array_of_float2x2_from_float2x2(h2x2) ? _uniforms.colorGreen : _uniforms.colorRed;
|
||||
return _out;
|
||||
}
|
||||
|
@ -16,6 +16,24 @@ bool operator==(thread const array<T1, N>& left, thread const array<T2, N>& righ
|
||||
template <typename T1, typename T2, size_t N>
|
||||
bool operator!=(thread const array<T1, N>& left, thread const array<T2, N>& right);
|
||||
|
||||
template <size_t N>
|
||||
array<int, N> array_of_int_from_int(thread const array<int, N>& x) {
|
||||
array<int, N> result;
|
||||
for (int i = 0; i < N; ++i) {
|
||||
result[i] = int(x[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
array<float, N> array_of_float_from_float(thread const array<float, N>& x) {
|
||||
array<float, N> result;
|
||||
for (int i = 0; i < N; ++i) {
|
||||
result[i] = float(x[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, size_t N>
|
||||
bool operator==(thread const array<T1, N>& left, thread const array<T2, N>& right) {
|
||||
for (size_t index = 0; index < N; ++index) {
|
||||
@ -37,11 +55,11 @@ fragment Outputs fragmentMain(Inputs _in [[stage_in]], constant Uniforms& _unifo
|
||||
array<int, 2> s2 = array<int, 2>{1, 2};
|
||||
array<float, 2> f2 = array<float, 2>{1.0, 2.0};
|
||||
array<float, 2> h2 = array<float, 2>{1.0, 2.0};
|
||||
i2 = s2;
|
||||
s2 = i2;
|
||||
f2 = h2;
|
||||
h2 = f2;
|
||||
i2 = array_of_int_from_int(s2);
|
||||
s2 = array_of_int_from_int(i2);
|
||||
f2 = array_of_float_from_float(h2);
|
||||
h2 = array_of_float_from_float(f2);
|
||||
const array<float, 2> cf2 = array<float, 2>{1.0, 2.0};
|
||||
_out.sk_FragColor = ((i2 == s2 && f2 == h2) && i2 == array<int, 2>{1, 2}) && h2 == cf2 ? _uniforms.colorGreen : _uniforms.colorRed;
|
||||
_out.sk_FragColor = ((i2 == array_of_int_from_int(s2) && f2 == array_of_float_from_float(h2)) && i2 == array<int, 2>{1, 2}) && array_of_float_from_float(h2) == cf2 ? _uniforms.colorGreen : _uniforms.colorRed;
|
||||
return _out;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user