Implement log and log2 intrinsics in SkRP. These already existed in Raster Pipeline, so they just needed to be wired up into the SkRP builder and codegen. I also ported over the SkVM unit test for log2 since we didn't have an RP equivalent. Change-Id: Ida15486084ebd76f50f9aaa3c3c0e7d0c1b399f8 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/658080 Auto-Submit: John Stiles <johnstiles@google.com> Reviewed-by: Brian Osman <brianosman@google.com> Commit-Queue: John Stiles <johnstiles@google.com>
diff --git a/src/core/SkRasterPipelineOpList.h b/src/core/SkRasterPipelineOpList.h index d1246b4..2d4a4f8 100644 --- a/src/core/SkRasterPipelineOpList.h +++ b/src/core/SkRasterPipelineOpList.h
@@ -130,6 +130,7 @@ M(sin_float) M(cos_float) M(tan_float) \ M(asin_float) M(acos_float) M(atan_float) M(atan2_n_floats) \ M(sqrt_float) M(pow_n_floats) M(exp_float) \ + M(log_float) M(log2_float) \ M(copy_constant) M(copy_2_constants) M(copy_3_constants) M(copy_4_constants) \ M(copy_slot_masked) M(copy_2_slots_masked) M(copy_3_slots_masked) M(copy_4_slots_masked) \ M(copy_from_indirect_unmasked) M(copy_from_indirect_uniform_unmasked) \
diff --git a/src/opts/SkRasterPipeline_opts.h b/src/opts/SkRasterPipeline_opts.h index 3eaeed0..49ab5de 100644 --- a/src/opts/SkRasterPipeline_opts.h +++ b/src/opts/SkRasterPipeline_opts.h
@@ -1035,7 +1035,7 @@ SI F fract(F v) { return v - floor_(v); } -// See http://www.machinedlearnings.com/2011/06/fast-approximate-logarithm-exponential.html. +// See http://www.machinedlearnings.com/2011/06/fast-approximate-logarithm-exponential.html SI F approx_log2(F x) { // e - 127 is a fair approximation of log2(x) in its own right... F e = cast(sk_bit_cast<U32>(x)) * (1.0f / (1<<23)); @@ -3719,6 +3719,8 @@ STAGE_TAIL(atan_float, F* dst) { *dst = atan_(*dst); } STAGE_TAIL(sqrt_float, F* dst) { *dst = sqrt_(*dst); } STAGE_TAIL(exp_float, F* dst) { *dst = approx_exp(*dst); } +STAGE_TAIL(log_float, F* dst) { *dst = approx_log(*dst); } +STAGE_TAIL(log2_float, F* dst) { *dst = approx_log2(*dst); } // Binary operations take two adjacent inputs, and write their output in the first position. template <typename T, void (*ApplyFn)(T*, T*)>
diff --git a/src/sksl/codegen/SkSLRasterPipelineBuilder.cpp b/src/sksl/codegen/SkSLRasterPipelineBuilder.cpp index 395cb94..b42a585 100644 --- a/src/sksl/codegen/SkSLRasterPipelineBuilder.cpp +++ b/src/sksl/codegen/SkSLRasterPipelineBuilder.cpp
@@ -42,6 +42,8 @@ case BuilderOp::atan_float: \ case BuilderOp::cos_float: \ case BuilderOp::exp_float: \ + case BuilderOp::log_float: \ + case BuilderOp::log2_float: \ case BuilderOp::sin_float: \ case BuilderOp::sqrt_float: \ case BuilderOp::tan_float @@ -2045,6 +2047,8 @@ case POp::ceil_float: case POp::cos_float: case POp::exp_float: + case POp::log_float: + case POp::log2_float: case POp::floor_float: case POp::sin_float: case POp::sqrt_float: @@ -2486,6 +2490,14 @@ opText = opArg1 + " = exp(" + opArg1 + ")"; break; + case POp::log_float: + opText = opArg1 + " = log(" + opArg1 + ")"; + break; + + case POp::log2_float: + opText = opArg1 + " = log2(" + opArg1 + ")"; + break; + case POp::pow_n_floats: opText = opArg1 + " = pow(" + opArg1 + ", " + opArg2 + ")"; break;
diff --git a/src/sksl/codegen/SkSLRasterPipelineCodeGenerator.cpp b/src/sksl/codegen/SkSLRasterPipelineCodeGenerator.cpp index 5a0e7d1..396f4b6 100644 --- a/src/sksl/codegen/SkSLRasterPipelineCodeGenerator.cpp +++ b/src/sksl/codegen/SkSLRasterPipelineCodeGenerator.cpp
@@ -2570,6 +2570,20 @@ return this->pushExpression(arg0) && this->pushLengthIntrinsic(arg0.type().slotCount()); + case IntrinsicKind::k_log_IntrinsicKind: + if (!this->pushExpression(arg0)) { + return unsupported(); + } + fBuilder.unary_op(BuilderOp::log_float, arg0.type().slotCount()); + return true; + + case IntrinsicKind::k_log2_IntrinsicKind: + if (!this->pushExpression(arg0)) { + return unsupported(); + } + fBuilder.unary_op(BuilderOp::log2_float, arg0.type().slotCount()); + return true; + case IntrinsicKind::k_normalize_IntrinsicKind: // Implement normalize as `x / length(x)`. First, push the expression. if (!this->pushExpression(arg0)) {
diff --git a/tests/SkRasterPipelineOptsTest.cpp b/tests/SkRasterPipelineOptsTest.cpp index d4e4cea..162bf2d 100644 --- a/tests/SkRasterPipelineOptsTest.cpp +++ b/tests/SkRasterPipelineOptsTest.cpp
@@ -175,3 +175,16 @@ } } } + +DEF_TEST(SkRasterPipelineOpts_Log2, r) { + using F = SK_OPTS_NS::F; + + constexpr float kTolerance = 0.001f; + for (float value : {0.25f, 0.5f, 1.0f, 2.0f, 4.0f, 8.0f}) { + F result = SK_OPTS_NS::approx_log2(value); + F expected = std::log2(value); + F delta = SK_OPTS_NS::abs_(expected - result); + + REPORTER_ASSERT(r, SK_OPTS_NS::all(delta < kTolerance)); + } +}
diff --git a/tests/sksl/intrinsics/Log.skrp b/tests/sksl/intrinsics/Log.skrp index 3ef3d71..eaa03e3 100644 --- a/tests/sksl/intrinsics/Log.skrp +++ b/tests/sksl/intrinsics/Log.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 $4 = inputVal(0) + 4. log_float $4 = log($4) + 5. copy_constant $5 = expected(0) + 6. cmpeq_float $4 = equal($4, $5) + 7. copy_2_constants $5..6 = inputVal(0..1) + 8. log_float $5 = log($5) + 9. log_float $6 = log($6) + 10. copy_2_constants $7..8 = expected(0..1) + 11. cmpeq_2_floats $5..6 = equal($5..6, $7..8) + 12. bitwise_and_int $5 &= $6 + 13. bitwise_and_int $4 &= $5 + 14. copy_3_constants $5..7 = inputVal(0..2) + 15. log_float $5 = log($5) + 16. log_float $6 = log($6) + 17. log_float $7 = log($7) + 18. copy_3_constants $8..10 = expected(0..2) + 19. cmpeq_3_floats $5..7 = equal($5..7, $8..10) + 20. bitwise_and_int $6 &= $7 + 21. bitwise_and_int $5 &= $6 + 22. bitwise_and_int $4 &= $5 + 23. copy_4_constants $5..8 = inputVal + 24. log_float $5 = log($5) + 25. log_float $6 = log($6) + 26. log_float $7 = log($7) + 27. log_float $8 = log($8) + 28. copy_4_constants $9..12 = expected + 29. cmpeq_4_floats $5..8 = equal($5..8, $9..12) + 30. bitwise_and_2_ints $5..6 &= $7..8 + 31. bitwise_and_int $5 &= $6 + 32. bitwise_and_int $4 &= $5 + 33. zero_slot_unmasked $5 = 0 + 34. copy_constant $6 = expected(0) + 35. cmpeq_float $5 = equal($5, $6) + 36. bitwise_and_int $4 &= $5 + 37. zero_2_slots_unmasked $5..6 = 0 + 38. copy_2_constants $7..8 = expected(0..1) + 39. cmpeq_2_floats $5..6 = equal($5..6, $7..8) + 40. bitwise_and_int $5 &= $6 + 41. bitwise_and_int $4 &= $5 + 42. zero_3_slots_unmasked $5..7 = 0 + 43. copy_3_constants $8..10 = expected(0..2) + 44. cmpeq_3_floats $5..7 = equal($5..7, $8..10) + 45. bitwise_and_int $6 &= $7 + 46. bitwise_and_int $5 &= $6 + 47. bitwise_and_int $4 &= $5 + 48. zero_4_slots_unmasked $5..8 = 0 + 49. copy_4_constants $9..12 = expected + 50. cmpeq_4_floats $5..8 = equal($5..8, $9..12) + 51. bitwise_and_2_ints $5..6 &= $7..8 + 52. bitwise_and_int $5 &= $6 + 53. bitwise_and_int $4 &= $5 + 54. branch_if_no_active_lanes_eq branch +3 (label 0 at #57) if no lanes of $4 == 0xFFFFFFFF + 55. copy_4_constants $0..3 = colorGreen + 56. jump jump +3 (label 1 at #59) + 57. label label 0x00000000 + 58. copy_4_constants $0..3 = colorRed + 59. label label 0x00000001 + 60. load_src src.rgba = $0..3
diff --git a/tests/sksl/intrinsics/Log2.skrp b/tests/sksl/intrinsics/Log2.skrp index 3ef3d71..bd4817c 100644 --- a/tests/sksl/intrinsics/Log2.skrp +++ b/tests/sksl/intrinsics/Log2.skrp
@@ -1,4 +1,66 @@ -### 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 $4 = inputVal(0) + 4. log2_float $4 = log2($4) + 5. copy_constant $5 = expected(0) + 6. cmpeq_float $4 = equal($4, $5) + 7. copy_2_constants $5..6 = inputVal(0..1) + 8. log2_float $5 = log2($5) + 9. log2_float $6 = log2($6) + 10. copy_2_constants $7..8 = expected(0..1) + 11. cmpeq_2_floats $5..6 = equal($5..6, $7..8) + 12. bitwise_and_int $5 &= $6 + 13. bitwise_and_int $4 &= $5 + 14. copy_3_constants $5..7 = inputVal(0..2) + 15. log2_float $5 = log2($5) + 16. log2_float $6 = log2($6) + 17. log2_float $7 = log2($7) + 18. copy_3_constants $8..10 = expected(0..2) + 19. cmpeq_3_floats $5..7 = equal($5..7, $8..10) + 20. bitwise_and_int $6 &= $7 + 21. bitwise_and_int $5 &= $6 + 22. bitwise_and_int $4 &= $5 + 23. copy_4_constants $5..8 = inputVal + 24. log2_float $5 = log2($5) + 25. log2_float $6 = log2($6) + 26. log2_float $7 = log2($7) + 27. log2_float $8 = log2($8) + 28. copy_4_constants $9..12 = expected + 29. cmpeq_4_floats $5..8 = equal($5..8, $9..12) + 30. bitwise_and_2_ints $5..6 &= $7..8 + 31. bitwise_and_int $5 &= $6 + 32. bitwise_and_int $4 &= $5 + 33. zero_slot_unmasked $5 = 0 + 34. copy_constant $6 = expected(0) + 35. cmpeq_float $5 = equal($5, $6) + 36. bitwise_and_int $4 &= $5 + 37. zero_slot_unmasked $5 = 0 + 38. copy_constant $6 = 0x3F800000 (1.0) + 39. copy_2_constants $7..8 = expected(0..1) + 40. cmpeq_2_floats $5..6 = equal($5..6, $7..8) + 41. bitwise_and_int $5 &= $6 + 42. bitwise_and_int $4 &= $5 + 43. zero_slot_unmasked $5 = 0 + 44. copy_constant $6 = 0x3F800000 (1.0) + 45. copy_constant $7 = 0x40000000 (2.0) + 46. copy_3_constants $8..10 = expected(0..2) + 47. cmpeq_3_floats $5..7 = equal($5..7, $8..10) + 48. bitwise_and_int $6 &= $7 + 49. bitwise_and_int $5 &= $6 + 50. bitwise_and_int $4 &= $5 + 51. zero_slot_unmasked $5 = 0 + 52. copy_constant $6 = 0x3F800000 (1.0) + 53. copy_constant $7 = 0x40000000 (2.0) + 54. copy_constant $8 = 0x40400000 (3.0) + 55. copy_4_constants $9..12 = expected + 56. cmpeq_4_floats $5..8 = equal($5..8, $9..12) + 57. bitwise_and_2_ints $5..6 &= $7..8 + 58. bitwise_and_int $5 &= $6 + 59. bitwise_and_int $4 &= $5 + 60. branch_if_no_active_lanes_eq branch +3 (label 0 at #63) if no lanes of $4 == 0xFFFFFFFF + 61. copy_4_constants $0..3 = colorGreen + 62. jump jump +3 (label 1 at #65) + 63. label label 0x00000000 + 64. copy_4_constants $0..3 = colorRed + 65. label label 0x00000001 + 66. load_src src.rgba = $0..3