diff options
author | mtklein <mtklein@chromium.org> | 2015-06-26 10:46:31 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-06-26 10:46:31 -0700 |
commit | 2aab22a58a366df4752c1cf0f004092c6e7be335 (patch) | |
tree | bc4026ca98f28068b99ca6394c05a0129f0dc4d6 /src/opts | |
parent | cdb42bb55c3bdbbd6682dcd50b5c77322bb6e565 (diff) |
Color dodge and burn with SkPMFloat.
Both 25-35% faster with SSE.
With NEON, Burn measures as a ~10% regression, Dodge a huge 2.9x improvement.
The Burn regression is somewhat artificial: we're drawing random colored rects onto an opaque white dst, so we're heavily biased toward the (d==da) fast path in the serial code. In the vector code there's no short-circuiting and we always pay a fixed cost for ColorBurn regardless of src or dst content.
Dodge's fast paths, in contrast, only trigger when (s==sa) or (d==0), neither of which happens any more than randomly in our benchmark. I don't think (d==0) should happen at all. Similarly, the (s==0) Burn fast path is really only going to happen as often as SkRandom allows.
In practice, the existing Burn benchmark is hitting its fast path 100% of the time. So I actually feel really great that this only dings the benchmark by 10%.
Chrome's still guarded by SK_SUPPORT_LEGACY_XFERMODES, which I'll lift after finishing the last xfermode, SoftLight.
BUG=skia:
Review URL: https://codereview.chromium.org/1214443002
Diffstat (limited to 'src/opts')
-rw-r--r-- | src/opts/SkNx_neon.h | 7 | ||||
-rw-r--r-- | src/opts/SkNx_sse.h | 5 | ||||
-rw-r--r-- | src/opts/SkPMFloat_neon.h | 5 | ||||
-rw-r--r-- | src/opts/SkPMFloat_none.h | 4 | ||||
-rw-r--r-- | src/opts/SkPMFloat_sse.h | 5 | ||||
-rw-r--r-- | src/opts/SkXfermode_opts_SSE2.cpp | 6 |
6 files changed, 29 insertions, 3 deletions
diff --git a/src/opts/SkNx_neon.h b/src/opts/SkNx_neon.h index b319807779..ccba163e56 100644 --- a/src/opts/SkNx_neon.h +++ b/src/opts/SkNx_neon.h @@ -297,6 +297,13 @@ public: || vgetq_lane_u32(v,2) || vgetq_lane_u32(v,3); } + SkNf thenElse(const SkNf& t, const SkNf& e) const { + uint32x4_t ci = vreinterpretq_u32_f32(fVec), + ti = vreinterpretq_u32_f32(t.fVec), + ei = vreinterpretq_u32_f32(e.fVec); + return vreinterpretq_f32_u32(vorrq_u32(vandq_u32(ti, ci), vbicq_u32(ei, ci))); + } + float32x4_t fVec; }; diff --git a/src/opts/SkNx_sse.h b/src/opts/SkNx_sse.h index 9b4de700ee..2d3acbe459 100644 --- a/src/opts/SkNx_sse.h +++ b/src/opts/SkNx_sse.h @@ -193,6 +193,11 @@ public: bool allTrue() const { return 0xffff == _mm_movemask_epi8(_mm_castps_si128(fVec)); } bool anyTrue() const { return 0x0000 != _mm_movemask_epi8(_mm_castps_si128(fVec)); } + SkNf thenElse(const SkNf& t, const SkNf& e) const { + return _mm_or_ps(_mm_and_ps (fVec, t.fVec), + _mm_andnot_ps(fVec, e.fVec)); + } + __m128 fVec; }; diff --git a/src/opts/SkPMFloat_neon.h b/src/opts/SkPMFloat_neon.h index c8976860b1..8bee5b551a 100644 --- a/src/opts/SkPMFloat_neon.h +++ b/src/opts/SkPMFloat_neon.h @@ -27,4 +27,9 @@ inline SkPMColor SkPMFloat::round() const { return c; } +inline Sk4f SkPMFloat::alphas() const { + static_assert(SK_A32_SHIFT == 24, "Assuming little-endian."); + return vdupq_lane_f32(vget_high_f32(fVec), 1); // Duplicate high lane of high half i.e. lane 3. +} + } // namespace diff --git a/src/opts/SkPMFloat_none.h b/src/opts/SkPMFloat_none.h index ba773564d6..518ad159ff 100644 --- a/src/opts/SkPMFloat_none.h +++ b/src/opts/SkPMFloat_none.h @@ -30,4 +30,8 @@ inline SkPMColor SkPMFloat::round() const { return c; } +inline Sk4f SkPMFloat::alphas() const { + return Sk4f(this->a()); +} + } // namespace diff --git a/src/opts/SkPMFloat_sse.h b/src/opts/SkPMFloat_sse.h index 802b17ba0c..28aa90bf29 100644 --- a/src/opts/SkPMFloat_sse.h +++ b/src/opts/SkPMFloat_sse.h @@ -33,4 +33,9 @@ inline SkPMColor SkPMFloat::round() const { return c; } +inline Sk4f SkPMFloat::alphas() const { + static_assert(SK_A32_SHIFT == 24, ""); + return _mm_shuffle_ps(fVec, fVec, 0xff); // Read as 11 11 11 11, copying lane 3 to all lanes. +} + } // namespace diff --git a/src/opts/SkXfermode_opts_SSE2.cpp b/src/opts/SkXfermode_opts_SSE2.cpp index f8772808a7..ca26263727 100644 --- a/src/opts/SkXfermode_opts_SSE2.cpp +++ b/src/opts/SkXfermode_opts_SSE2.cpp @@ -521,11 +521,11 @@ SkProcCoeffXfermode* SkPlatformXfermodeFactory_impl_SSE2(const ProcCoeff& rec, case SkProcCoeffXfermode::kDarken_Mode: proc = darken_modeproc_SSE2; break; case SkProcCoeffXfermode::kLighten_Mode: proc = lighten_modeproc_SSE2; break; case SkProcCoeffXfermode::kHardLight_Mode: proc = hardlight_modeproc_SSE2; break; - - // TODO(mtklein): implement these with SkPMFloat. - case SkProcCoeffXfermode::kSoftLight_Mode: proc = softlight_modeproc_SSE2; break; case SkProcCoeffXfermode::kColorDodge_Mode: proc = colordodge_modeproc_SSE2; break; case SkProcCoeffXfermode::kColorBurn_Mode: proc = colorburn_modeproc_SSE2; break; + + // TODO(mtklein): implement this with SkPMFloat. + case SkProcCoeffXfermode::kSoftLight_Mode: proc = softlight_modeproc_SSE2; break; default: break; } return proc ? SkNEW_ARGS(SkSSE2ProcCoeffXfermode, (rec, mode, (void*)proc)) : nullptr; |