Implement distance intrinsic in RP codegen.
This is implemented in terms of the existing `length` intrinsic.
Change-Id: Ib2cfc0e5078e10e571551a9ee37f7911b62e2e66
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/657738
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Jim Van Verth <jvanverth@google.com>
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
Commit-Queue: Jim Van Verth <jvanverth@google.com>
diff --git a/src/sksl/codegen/SkSLRasterPipelineCodeGenerator.cpp b/src/sksl/codegen/SkSLRasterPipelineCodeGenerator.cpp
index 670e408..a66178f 100644
--- a/src/sksl/codegen/SkSLRasterPipelineCodeGenerator.cpp
+++ b/src/sksl/codegen/SkSLRasterPipelineCodeGenerator.cpp
@@ -295,6 +295,7 @@
[[nodiscard]] bool pushIntrinsic(BuilderOp builderOp,
const Expression& arg0,
const Expression& arg1);
+ [[nodiscard]] bool pushLengthIntrinsic(int slotCount);
[[nodiscard]] bool pushVectorizedExpression(const Expression& expr, const Type& vectorType);
[[nodiscard]] bool pushVariableReferencePartial(const VariableReference& v, SlotRange subset);
[[nodiscard]] bool pushLValueOrExpression(LValue* lvalue, const Expression& expr);
@@ -2460,6 +2461,19 @@
return unsupported();
}
+bool Generator::pushLengthIntrinsic(int slotCount) {
+ if (slotCount > 1) {
+ // Implement `length(vec)` as `sqrt(dot(x, x))`.
+ fBuilder.push_clone(slotCount);
+ fBuilder.dot_floats(slotCount);
+ fBuilder.unary_op(BuilderOp::sqrt_float, 1);
+ } else {
+ // `length(scalar)` is `sqrt(x^2)`, which is equivalent to `abs(x)`.
+ fBuilder.unary_op(BuilderOp::abs_float, 1);
+ }
+ return true;
+}
+
bool Generator::pushVectorizedExpression(const Expression& expr, const Type& vectorType) {
if (!this->pushExpression(expr)) {
return unsupported();
@@ -2547,19 +2561,8 @@
this->binaryOp(arg0.type(), kDivideOps);
}
case IntrinsicKind::k_length_IntrinsicKind:
- if (!this->pushExpression(arg0)) {
- return unsupported();
- }
- // Implement length as `sqrt(dot(x, x))`.
- if (arg0.type().slotCount() > 1) {
- fBuilder.push_clone(arg0.type().slotCount());
- fBuilder.dot_floats(arg0.type().slotCount());
- fBuilder.unary_op(BuilderOp::sqrt_float, 1);
- } else {
- // The length of a scalar is `sqrt(x^2)`, which is equivalent to `abs(x)`.
- fBuilder.unary_op(BuilderOp::abs_float, 1);
- }
- return true;
+ return this->pushExpression(arg0) &&
+ this->pushLengthIntrinsic(arg0.type().slotCount());
case IntrinsicKind::k_not_IntrinsicKind:
return this->pushPrefixExpression(OperatorKind::LOGICALNOT, arg0);
@@ -2734,8 +2737,13 @@
subexpressionStack.exit();
return true;
}
+ case IntrinsicKind::k_distance_IntrinsicKind:
+ // Implement distance as `length(a - b)`.
+ SkASSERT(arg0.type().slotCount() == arg1.type().slotCount());
+ return this->pushBinaryExpression(arg0, OperatorKind::MINUS, arg1) &&
+ this->pushLengthIntrinsic(arg0.type().slotCount());
+
case IntrinsicKind::k_dot_IntrinsicKind:
- // Implement dot as `a*b`, followed by folding via addition.
SkASSERT(arg0.type().matches(arg1.type()));
if (!this->pushExpression(arg0) || !this->pushExpression(arg1)) {
return unsupported();
diff --git a/tests/sksl/intrinsics/Distance.skrp b/tests/sksl/intrinsics/Distance.skrp
index 3ef3d71..8ca4c0d 100644
--- a/tests/sksl/intrinsics/Distance.skrp
+++ b/tests/sksl/intrinsics/Distance.skrp
@@ -1,4 +1,60 @@
-### Compilation failed:
-
-error: code is not supported
-1 error
+ 1. store_src_rg coords = src.rg
+ 2. init_lane_masks CondMask = LoopMask = RetMask = true
+ 3. copy_constant expected(0) = 0x40400000 (3.0)
+ 4. copy_constant expected(1) = 0x40400000 (3.0)
+ 5. copy_constant expected(2) = 0x40A00000 (5.0)
+ 6. copy_constant expected(3) = 0x41500000 (13.0)
+ 7. copy_constant $0 = pos1(0)
+ 8. copy_constant $1 = pos2(0)
+ 9. sub_float $0 -= $1
+ 10. abs_float $0 = abs($0)
+ 11. copy_slot_unmasked $1 = expected(0)
+ 12. cmpeq_float $0 = equal($0, $1)
+ 13. copy_2_constants $1..2 = pos1(0..1)
+ 14. copy_2_constants $3..4 = pos2(0..1)
+ 15. sub_2_floats $1..2 -= $3..4
+ 16. copy_2_slots_unmasked $3..4 = $1..2
+ 17. dot_2_floats $1 = dot($1..2, $3..4)
+ 18. sqrt_float $1 = sqrt($1)
+ 19. copy_slot_unmasked $2 = expected(1)
+ 20. cmpeq_float $1 = equal($1, $2)
+ 21. bitwise_and_int $0 &= $1
+ 22. copy_3_constants $1..3 = pos1(0..2)
+ 23. copy_3_constants $4..6 = pos2(0..2)
+ 24. sub_3_floats $1..3 -= $4..6
+ 25. copy_3_slots_unmasked $4..6 = $1..3
+ 26. dot_3_floats $1 = dot($1..3, $4..6)
+ 27. sqrt_float $1 = sqrt($1)
+ 28. copy_slot_unmasked $2 = expected(2)
+ 29. cmpeq_float $1 = equal($1, $2)
+ 30. bitwise_and_int $0 &= $1
+ 31. copy_4_constants $1..4 = pos1
+ 32. copy_4_constants $5..8 = pos2
+ 33. sub_4_floats $1..4 -= $5..8
+ 34. copy_4_slots_unmasked $5..8 = $1..4
+ 35. dot_4_floats $1 = dot($1..4, $5..8)
+ 36. sqrt_float $1 = sqrt($1)
+ 37. copy_slot_unmasked $2 = expected(3)
+ 38. cmpeq_float $1 = equal($1, $2)
+ 39. bitwise_and_int $0 &= $1
+ 40. copy_constant $1 = 0x40400000 (3.0)
+ 41. copy_slot_unmasked $2 = expected(0)
+ 42. cmpeq_float $1 = equal($1, $2)
+ 43. bitwise_and_int $0 &= $1
+ 44. copy_constant $1 = 0x40400000 (3.0)
+ 45. copy_slot_unmasked $2 = expected(1)
+ 46. cmpeq_float $1 = equal($1, $2)
+ 47. bitwise_and_int $0 &= $1
+ 48. copy_constant $1 = 0x40A00000 (5.0)
+ 49. copy_slot_unmasked $2 = expected(2)
+ 50. cmpeq_float $1 = equal($1, $2)
+ 51. bitwise_and_int $0 &= $1
+ 52. copy_constant $1 = 0x41500000 (13.0)
+ 53. copy_slot_unmasked $2 = expected(3)
+ 54. cmpeq_float $1 = equal($1, $2)
+ 55. bitwise_and_int $0 &= $1
+ 56. swizzle_4 $0..3 = ($0..3).xxxx
+ 57. copy_4_constants $4..7 = colorRed
+ 58. copy_4_constants $8..11 = colorGreen
+ 59. mix_4_ints $0..3 = mix($4..7, $8..11, $0..3)
+ 60. load_src src.rgba = $0..3