diff options
author | Mike Klein <mtklein@chromium.org> | 2016-09-29 13:40:01 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2016-09-29 18:11:29 +0000 |
commit | fa9f241a85c55c32a3fe2ae0324811de998f7a2e (patch) | |
tree | 01308fe5602180eaaf0636fa635183ce9a93a7e7 | |
parent | 69e7eba6aef583eb0561019539b164d8e0eed025 (diff) |
Add an enum layer of indirection for stock raster pipeline stages.
This is handy now, and becomes necessary with fancier backends:
- most code can't speak the type of AVX pipeline stages,
so indirection's definitely needed there;
- if the pipleine is entirely composed of stock stages,
these enum values become an abstract recipe that can be JITted.
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2782
CQ_INCLUDE_TRYBOTS=master.client.skia:Test-Ubuntu-GCC-GCE-CPU-AVX2-x86_64-Release-SKNX_NO_SIMD-Trybot
Change-Id: Iedd62e99ce39e94cf3e6ffc78c428f0ccc182342
Reviewed-on: https://skia-review.googlesource.com/2782
Reviewed-by: Mike Klein <mtklein@chromium.org>
Commit-Queue: Mike Klein <mtklein@chromium.org>
-rw-r--r-- | bench/SkRasterPipelineBench.cpp | 10 | ||||
-rw-r--r-- | src/core/SkOpts.cpp | 68 | ||||
-rw-r--r-- | src/core/SkOpts.h | 20 | ||||
-rw-r--r-- | src/core/SkRasterPipeline.cpp | 5 | ||||
-rw-r--r-- | src/core/SkRasterPipeline.h | 27 | ||||
-rw-r--r-- | src/core/SkRasterPipelineBlitter.cpp | 22 | ||||
-rw-r--r-- | src/opts/SkOpts_sse41.cpp | 36 | ||||
-rw-r--r-- | src/opts/SkRasterPipeline_opts.h | 20 |
8 files changed, 121 insertions, 87 deletions
diff --git a/bench/SkRasterPipelineBench.cpp b/bench/SkRasterPipelineBench.cpp index 17a93da549..a5e53471cd 100644 --- a/bench/SkRasterPipelineBench.cpp +++ b/bench/SkRasterPipelineBench.cpp @@ -30,11 +30,11 @@ public: void onDraw(int loops, SkCanvas*) override { while (loops --> 0) { SkRasterPipeline p; - p.append(SkOpts::load_s_srgb_body, SkOpts::load_s_srgb_tail, src); - p.append(SkOpts::scale_u8_body, SkOpts::scale_u8_tail, mask); - p.append(SkOpts::load_d_srgb_body, SkOpts::load_d_srgb_tail, dst); - p.append(SkOpts::srcover); - p.append(SkOpts::store_srgb_body, SkOpts::store_srgb_tail, dst); + p.append(SkRasterPipeline::load_s_srgb, src); + p.append(SkRasterPipeline:: scale_u8, mask); + p.append(SkRasterPipeline::load_d_srgb, dst); + p.append(SkRasterPipeline:: srcover); + p.append(SkRasterPipeline:: store_srgb, dst); p.run(N); } } diff --git a/src/core/SkOpts.cpp b/src/core/SkOpts.cpp index 1f686ff56b..5cac8ec3ca 100644 --- a/src/core/SkOpts.cpp +++ b/src/core/SkOpts.cpp @@ -90,37 +90,57 @@ namespace SkOpts { DEFINE_DEFAULT(hash_fn); #undef DEFINE_DEFAULT -// Stages that are not sensitive to the tail parameter can be represented by one function. -#define DEFINE_DEFAULT(stage, kCallNext) \ - decltype(stage) stage = body<SK_OPTS_NS::stage, kCallNext> + // TODO: might be nice to only create one instance of tail-insensitive stages. - DEFINE_DEFAULT(srcover, true); - DEFINE_DEFAULT(constant_color, true); - DEFINE_DEFAULT(lerp_constant_float, true); -#undef DEFINE_DEFAULT + SkRasterPipeline::Fn stages_4[] = { + stage_4<SK_OPTS_NS::store_565 , false>, + stage_4<SK_OPTS_NS::store_srgb, false>, + stage_4<SK_OPTS_NS::store_f16 , false>, -// Stages that are sensitive to the tail parameter need two versions, _body and _tail. -#define DEFINE_DEFAULT(stage, kCallNext) \ - decltype(stage##_body) stage##_body = body<SK_OPTS_NS::stage, kCallNext>; \ - decltype(stage##_tail) stage##_tail = tail<SK_OPTS_NS::stage, kCallNext> + stage_4<SK_OPTS_NS::load_s_565 , true>, + stage_4<SK_OPTS_NS::load_s_srgb, true>, + stage_4<SK_OPTS_NS::load_s_f16 , true>, - DEFINE_DEFAULT(load_d_srgb, true); - DEFINE_DEFAULT(load_s_srgb, true); - DEFINE_DEFAULT( store_srgb, false); + stage_4<SK_OPTS_NS::load_d_565 , true>, + stage_4<SK_OPTS_NS::load_d_srgb, true>, + stage_4<SK_OPTS_NS::load_d_f16 , true>, - DEFINE_DEFAULT(load_d_f16, true); - DEFINE_DEFAULT(load_s_f16, true); - DEFINE_DEFAULT( store_f16, false); + stage_4<SK_OPTS_NS::scale_u8, true>, - DEFINE_DEFAULT(load_d_565, true); - DEFINE_DEFAULT(load_s_565, true); - DEFINE_DEFAULT( store_565, false); + stage_4<SK_OPTS_NS::lerp_u8 , true>, + stage_4<SK_OPTS_NS::lerp_565 , true>, + stage_4<SK_OPTS_NS::lerp_constant_float, true>, - DEFINE_DEFAULT(scale_u8, true); + stage_4<SK_OPTS_NS::constant_color, true>, - DEFINE_DEFAULT(lerp_u8, true); - DEFINE_DEFAULT(lerp_565, true); -#undef DEFINE_DEFAULT + stage_4<SK_OPTS_NS::srcover, true>, + }; + static_assert(SK_ARRAY_COUNT(stages_4) == SkRasterPipeline::kNumStockStages, ""); + + SkRasterPipeline::Fn stages_1_3[] = { + stage_1_3<SK_OPTS_NS::store_565 , false>, + stage_1_3<SK_OPTS_NS::store_srgb, false>, + stage_1_3<SK_OPTS_NS::store_f16 , false>, + + stage_1_3<SK_OPTS_NS::load_s_565 , true>, + stage_1_3<SK_OPTS_NS::load_s_srgb, true>, + stage_1_3<SK_OPTS_NS::load_s_f16 , true>, + + stage_1_3<SK_OPTS_NS::load_d_565 , true>, + stage_1_3<SK_OPTS_NS::load_d_srgb, true>, + stage_1_3<SK_OPTS_NS::load_d_f16 , true>, + + stage_1_3<SK_OPTS_NS::scale_u8, true>, + + stage_1_3<SK_OPTS_NS::lerp_u8 , true>, + stage_1_3<SK_OPTS_NS::lerp_565 , true>, + stage_1_3<SK_OPTS_NS::lerp_constant_float, true>, + + stage_1_3<SK_OPTS_NS::constant_color, true>, + + stage_1_3<SK_OPTS_NS::srcover, true>, + }; + static_assert(SK_ARRAY_COUNT(stages_1_3) == SkRasterPipeline::kNumStockStages, ""); // Each Init_foo() is defined in src/opts/SkOpts_foo.cpp. void Init_ssse3(); diff --git a/src/core/SkOpts.h b/src/core/SkOpts.h index c310a79aa0..50de9c45e2 100644 --- a/src/core/SkOpts.h +++ b/src/core/SkOpts.h @@ -73,24 +73,8 @@ namespace SkOpts { return hash_fn(data, bytes, seed); } - // Each of the SkRasterPipeline::Fn's lists its context pointer type in the comments. - - extern SkRasterPipeline::Fn srcover, // (none) - constant_color, // const SkPM4f* - lerp_constant_float; // const float*, in [0,1] - - extern SkRasterPipeline::Fn load_d_srgb_body, load_d_srgb_tail, // const uint32_t* - load_s_srgb_body, load_s_srgb_tail, // const uint32_t* - store_srgb_body, store_srgb_tail, // uint32_t* - load_d_f16_body, load_d_f16_tail, // const uint64_t* - load_s_f16_body, load_s_f16_tail, // const uint64_t* - store_f16_body, store_f16_tail, // uint64_t* - load_d_565_body, load_d_565_tail, // const uint16_t* - load_s_565_body, load_s_565_tail, // const uint16_t* - store_565_body, store_565_tail, // uint16_t* - scale_u8_body, scale_u8_tail, // const uint8_t* - lerp_u8_body, lerp_u8_tail, // const uint8_t* - lerp_565_body, lerp_565_tail; // const uint16_t* + extern SkRasterPipeline::Fn stages_4 [SkRasterPipeline::kNumStockStages], + stages_1_3[SkRasterPipeline::kNumStockStages]; } #endif//SkOpts_DEFINED diff --git a/src/core/SkRasterPipeline.cpp b/src/core/SkRasterPipeline.cpp index 71c993dfb8..fd909a1205 100644 --- a/src/core/SkRasterPipeline.cpp +++ b/src/core/SkRasterPipeline.cpp @@ -5,6 +5,7 @@ * found in the LICENSE file. */ +#include "SkOpts.h" #include "SkRasterPipeline.h" SkRasterPipeline::SkRasterPipeline() {} @@ -23,6 +24,10 @@ void SkRasterPipeline::append(SkRasterPipeline::Fn body, fTail.push_back({ &JustReturn, const_cast<void*>(ctx) }); } +void SkRasterPipeline::append(StockStage stage, const void* ctx) { + this->append(SkOpts::stages_4[stage], SkOpts::stages_1_3[stage], ctx); +} + void SkRasterPipeline::extend(const SkRasterPipeline& src) { SkASSERT(src.fBody.count() == src.fTail.count()); diff --git a/src/core/SkRasterPipeline.h b/src/core/SkRasterPipeline.h index 9f4dcb34da..789257e0e2 100644 --- a/src/core/SkRasterPipeline.h +++ b/src/core/SkRasterPipeline.h @@ -88,6 +88,33 @@ public: void append(Fn body, Fn tail, const void* ctx = nullptr); void append(Fn fn, const void* ctx = nullptr) { this->append(fn, fn, ctx); } + enum StockStage { + store_565, + store_srgb, + store_f16, + + load_s_565, + load_s_srgb, + load_s_f16, + + load_d_565, + load_d_srgb, + load_d_f16, + + scale_u8, + + lerp_u8, + lerp_565, + lerp_constant_float, + + constant_color, + + srcover, + + kNumStockStages, + }; + void append(StockStage, const void* ctx=nullptr); + // Append all stages to this pipeline. void extend(const SkRasterPipeline&); diff --git a/src/core/SkRasterPipelineBlitter.cpp b/src/core/SkRasterPipelineBlitter.cpp index 2ada336cd8..1e8dcf59e0 100644 --- a/src/core/SkRasterPipelineBlitter.cpp +++ b/src/core/SkRasterPipelineBlitter.cpp @@ -102,10 +102,10 @@ SkBlitter* SkRasterPipelineBlitter::Create(const SkPixmap& dst, color.premul()); if (!paint.getShader()) { - blitter->fShader.append(SkOpts::constant_color, &blitter->fPaintColor); + blitter->fShader.append(SkRasterPipeline::constant_color, &blitter->fPaintColor); } if (!paint.getXfermode()) { - blitter->fXfermode.append(SkOpts::srcover); + blitter->fXfermode.append(SkRasterPipeline::srcover); } return blitter; @@ -117,14 +117,14 @@ void SkRasterPipelineBlitter::append_load_d(SkRasterPipeline* p, const void* dst switch (fDst.info().colorType()) { case kN32_SkColorType: if (fDst.info().gammaCloseToSRGB()) { - p->append(SkOpts::load_d_srgb_body, SkOpts::load_d_srgb_tail, dst); + p->append(SkRasterPipeline::load_d_srgb, dst); } break; case kRGBA_F16_SkColorType: - p->append(SkOpts::load_d_f16_body, SkOpts::load_d_f16_tail, dst); + p->append(SkRasterPipeline::load_d_f16, dst); break; case kRGB_565_SkColorType: - p->append(SkOpts::load_d_565_body, SkOpts::load_d_565_tail, dst); + p->append(SkRasterPipeline::load_d_565, dst); break; default: break; } @@ -136,14 +136,14 @@ void SkRasterPipelineBlitter::append_store(SkRasterPipeline* p, void* dst) const switch (fDst.info().colorType()) { case kN32_SkColorType: if (fDst.info().gammaCloseToSRGB()) { - p->append(SkOpts::store_srgb_body, SkOpts::store_srgb_tail, dst); + p->append(SkRasterPipeline::store_srgb, dst); } break; case kRGBA_F16_SkColorType: - p->append(SkOpts::store_f16_body, SkOpts::store_f16_tail, dst); + p->append(SkRasterPipeline::store_f16, dst); break; case kRGB_565_SkColorType: - p->append(SkOpts::store_565_body, SkOpts::store_565_tail, dst); + p->append(SkRasterPipeline::store_565, dst); break; default: break; } @@ -171,7 +171,7 @@ void SkRasterPipelineBlitter::blitAntiH(int x, int y, const SkAlpha aa[], const p.extend(fColorFilter); this->append_load_d(&p, dst); p.extend(fXfermode); - p.append(SkOpts::lerp_constant_float, &coverage); + p.append(SkRasterPipeline::lerp_constant_float, &coverage); this->append_store(&p, dst); for (int16_t run = *runs; run > 0; run = *runs) { @@ -201,10 +201,10 @@ void SkRasterPipelineBlitter::blitMask(const SkMask& mask, const SkIRect& clip) p.extend(fXfermode); switch (mask.fFormat) { case SkMask::kA8_Format: - p.append(SkOpts::lerp_u8_body, SkOpts::lerp_u8_tail, mask.getAddr8(x,y)-x); + p.append(SkRasterPipeline::lerp_u8, mask.getAddr8(x,y)-x); break; case SkMask::kLCD16_Format: - p.append(SkOpts::lerp_565_body, SkOpts::lerp_565_tail, mask.getAddrLCD16(x,y)-x); + p.append(SkRasterPipeline::lerp_565, mask.getAddrLCD16(x,y)-x); break; default: break; } diff --git a/src/opts/SkOpts_sse41.cpp b/src/opts/SkOpts_sse41.cpp index e4e3246780..0509b91fdf 100644 --- a/src/opts/SkOpts_sse41.cpp +++ b/src/opts/SkOpts_sse41.cpp @@ -22,33 +22,31 @@ namespace SkOpts { blit_row_s32a_opaque = sse41::blit_row_s32a_opaque; #define STAGE(stage, kCallNext) \ - stage = body<SK_OPTS_NS::stage, kCallNext> + stages_4 [SkRasterPipeline::stage] = stage_4 <SK_OPTS_NS::stage, kCallNext>; \ + stages_1_3[SkRasterPipeline::stage] = stage_1_3<SK_OPTS_NS::stage, kCallNext> - STAGE(srcover, true); - STAGE(constant_color, true); - STAGE(lerp_constant_float, true); - #undef STAGE + STAGE(store_565 , false); + STAGE(store_srgb, false); + STAGE(store_f16 , false); - #define STAGE(stage, kCallNext) \ - stage##_body = body<SK_OPTS_NS::stage, kCallNext>; \ - stage##_tail = tail<SK_OPTS_NS::stage, kCallNext> + STAGE(load_s_565 , true); + STAGE(load_s_srgb, true); + STAGE(load_s_f16 , true); + STAGE(load_d_565 , true); STAGE(load_d_srgb, true); - STAGE(load_s_srgb, true); - STAGE( store_srgb, false); + STAGE(load_d_f16 , true); - STAGE(load_d_f16, true); - STAGE(load_s_f16, true); - STAGE( store_f16, false); + STAGE(scale_u8, true); - STAGE(load_d_565, true); - STAGE(load_s_565, true); - STAGE( store_565, false); + STAGE(lerp_u8 , true); + STAGE(lerp_565 , true); + STAGE(lerp_constant_float, true); - STAGE(scale_u8, true); + STAGE(constant_color, true); - STAGE(lerp_u8, true); - STAGE(lerp_565, true); + STAGE(srcover, true); #undef STAGE + } } diff --git a/src/opts/SkRasterPipeline_opts.h b/src/opts/SkRasterPipeline_opts.h index 70c4d0c225..fe0fde8139 100644 --- a/src/opts/SkRasterPipeline_opts.h +++ b/src/opts/SkRasterPipeline_opts.h @@ -25,26 +25,26 @@ using Kernel_Sk4f = void(void*, size_t, size_t, Sk4f&, Sk4f&, Sk4f&, Sk4f&, template <Kernel_Sk4f kernel, bool kCallNext> -static inline void SK_VECTORCALL body(SkRasterPipeline::Stage* st, size_t x, size_t t, - Sk4f r, Sk4f g, Sk4f b, Sk4f a, - Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) { +static inline void SK_VECTORCALL stage_4(SkRasterPipeline::Stage* st, size_t x, size_t tail, + Sk4f r, Sk4f g, Sk4f b, Sk4f a, + Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) { // Passing 0 lets the optimizer completely drop any "if (tail) {...}" code in kernel. kernel(st->ctx<void*>(), x,0, r,g,b,a, dr,dg,db,da); if (kCallNext) { - st->next(x,t, r,g,b,a, dr,dg,db,da); // It's faster to pass t here than 0. + st->next(x,tail, r,g,b,a, dr,dg,db,da); // It's faster to pass t here than 0. } } template <Kernel_Sk4f kernel, bool kCallNext> -static inline void SK_VECTORCALL tail(SkRasterPipeline::Stage* st, size_t x, size_t t, - Sk4f r, Sk4f g, Sk4f b, Sk4f a, - Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) { +static inline void SK_VECTORCALL stage_1_3(SkRasterPipeline::Stage* st, size_t x, size_t tail, + Sk4f r, Sk4f g, Sk4f b, Sk4f a, + Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) { #if defined(__clang__) - __builtin_assume(t > 0); // This flourish lets Clang compile away any tail==0 code. + __builtin_assume(tail > 0); // This flourish lets Clang compile away any tail==0 code. #endif - kernel(st->ctx<void*>(), x,t, r,g,b,a, dr,dg,db,da); + kernel(st->ctx<void*>(), x,tail, r,g,b,a, dr,dg,db,da); if (kCallNext) { - st->next(x,t, r,g,b,a, dr,dg,db,da); + st->next(x,tail, r,g,b,a, dr,dg,db,da); } } |