diff options
author | Mike Klein <mtklein@chromium.org> | 2016-10-25 13:31:21 -0400 |
---|---|---|
committer | Mike Klein <mtklein@chromium.org> | 2016-10-25 18:04:16 +0000 |
commit | e9f74b89c09772dd5abae1c0709c711d7cdb6535 (patch) | |
tree | 96e72a059facdc06f0ea39f2037e77d08eac6453 | |
parent | aebfb45104eeb6dab5dbbedda13c2eaa7b7f7868 (diff) |
SkRasterPipeline::compile().
I'm not yet caching these in the blitter, and speed is essentially unchanged in the bench where I am now building and compiling the pipeline only once. This may not be able to stay a simple std::function after I figure out caching, but for now it's a nice fit.
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=3911
Change-Id: I9545af589f73baf9f17cb4e6ace9a814c2478fe9
Reviewed-on: https://skia-review.googlesource.com/3911
Reviewed-by: Herb Derby <herb@google.com>
Commit-Queue: Mike Klein <mtklein@chromium.org>
-rw-r--r-- | bench/SkRasterPipelineBench.cpp | 20 | ||||
-rw-r--r-- | src/core/SkOpts.cpp | 2 | ||||
-rw-r--r-- | src/core/SkOpts.h | 4 | ||||
-rw-r--r-- | src/core/SkRasterPipeline.cpp | 4 | ||||
-rw-r--r-- | src/core/SkRasterPipeline.h | 8 | ||||
-rw-r--r-- | src/core/SkRasterPipelineBlitter.cpp | 8 | ||||
-rw-r--r-- | src/opts/SkOpts_hsw.cpp | 2 | ||||
-rw-r--r-- | src/opts/SkOpts_sse41.cpp | 2 | ||||
-rw-r--r-- | src/opts/SkRasterPipeline_opts.h | 71 | ||||
-rw-r--r-- | tests/SkRasterPipelineTest.cpp | 6 |
10 files changed, 66 insertions, 61 deletions
diff --git a/bench/SkRasterPipelineBench.cpp b/bench/SkRasterPipelineBench.cpp index bf71d9a8d9..bfe2110362 100644 --- a/bench/SkRasterPipelineBench.cpp +++ b/bench/SkRasterPipelineBench.cpp @@ -32,16 +32,18 @@ public: } void onDraw(int loops, SkCanvas*) override { + SkRasterPipeline p; + p.append(SkRasterPipeline::load_s_srgb, src); + p.append(SkRasterPipeline:: scale_u8, mask); + p.append(kF16 ? SkRasterPipeline::load_d_f16 + : SkRasterPipeline::load_d_srgb, dst); + p.append(SkRasterPipeline:: srcover); + p.append(kF16 ? SkRasterPipeline::store_f16 + : SkRasterPipeline::store_srgb, dst); + auto compiled = p.compile(); + while (loops --> 0) { - SkRasterPipeline p; - p.append(SkRasterPipeline::load_s_srgb, src); - p.append(SkRasterPipeline:: scale_u8, mask); - p.append(kF16 ? SkRasterPipeline::load_d_f16 - : SkRasterPipeline::load_d_srgb, dst); - p.append(SkRasterPipeline:: srcover); - p.append(kF16 ? SkRasterPipeline::store_f16 - : SkRasterPipeline::store_srgb, dst); - p.run(N); + compiled(0, N); } } }; diff --git a/src/core/SkOpts.cpp b/src/core/SkOpts.cpp index c082b160ee..6648909d1a 100644 --- a/src/core/SkOpts.cpp +++ b/src/core/SkOpts.cpp @@ -89,7 +89,7 @@ namespace SkOpts { DEFINE_DEFAULT(hash_fn); - DEFINE_DEFAULT(run_pipeline); + DEFINE_DEFAULT(compile_pipeline); #undef DEFINE_DEFAULT // Each Init_foo() is defined in src/opts/SkOpts_foo.cpp. diff --git a/src/core/SkOpts.h b/src/core/SkOpts.h index 7283030068..8e1b7fec8a 100644 --- a/src/core/SkOpts.h +++ b/src/core/SkOpts.h @@ -12,6 +12,7 @@ #include "SkTextureCompressor.h" #include "SkTypes.h" #include "SkXfermode.h" +#include <functional> struct ProcCoeff; @@ -73,7 +74,8 @@ namespace SkOpts { return hash_fn(data, bytes, seed); } - extern void (*run_pipeline)(size_t, size_t, const SkRasterPipeline::Stage*, int); + extern + std::function<void(size_t, size_t)> (*compile_pipeline)(const SkRasterPipeline::Stage*, int); } #endif//SkOpts_DEFINED diff --git a/src/core/SkRasterPipeline.cpp b/src/core/SkRasterPipeline.cpp index 707a33ae6f..54de6793b0 100644 --- a/src/core/SkRasterPipeline.cpp +++ b/src/core/SkRasterPipeline.cpp @@ -22,6 +22,6 @@ void SkRasterPipeline::extend(const SkRasterPipeline& src) { } } -void SkRasterPipeline::run(size_t x, size_t n) const { - SkOpts::run_pipeline(x,n, fStages, fNum); +std::function<void(size_t, size_t)> SkRasterPipeline::compile() const { + return SkOpts::compile_pipeline(fStages, fNum); } diff --git a/src/core/SkRasterPipeline.h b/src/core/SkRasterPipeline.h index 60279dd168..548e503c84 100644 --- a/src/core/SkRasterPipeline.h +++ b/src/core/SkRasterPipeline.h @@ -11,6 +11,7 @@ #include "SkNx.h" #include "SkTArray.h" #include "SkTypes.h" +#include <functional> /** * SkRasterPipeline provides a cheap way to chain together a pixel processing pipeline. @@ -85,11 +86,8 @@ public: // Append all stages to this pipeline. void extend(const SkRasterPipeline&); - // Run the pipeline constructed with append(), walking x through [x,x+n), - // generally in 4-pixel steps, with perhaps one jagged tail step. - void run(size_t x, size_t n) const; - void run(size_t n) const { this->run(0, n); } - + // Runs the pipeline walking x through [x,x+n). + std::function<void(size_t x, size_t n)> compile() const; struct Stage { StockStage stage; diff --git a/src/core/SkRasterPipelineBlitter.cpp b/src/core/SkRasterPipelineBlitter.cpp index 91d60bee3a..ec634c8b98 100644 --- a/src/core/SkRasterPipelineBlitter.cpp +++ b/src/core/SkRasterPipelineBlitter.cpp @@ -149,6 +149,8 @@ void SkRasterPipelineBlitter::append_store(SkRasterPipeline* p, void* dst) const } } +// TODO: Figure out how to cache some of the compiled pipelines. + void SkRasterPipelineBlitter::blitH(int x, int y, int w) { auto dst = fDst.writable_addr(0,y); @@ -159,7 +161,7 @@ void SkRasterPipelineBlitter::blitH(int x, int y, int w) { p.extend(fXfermode); this->append_store(&p, dst); - p.run(x, w); + p.compile()(x,w); } void SkRasterPipelineBlitter::blitAntiH(int x, int y, const SkAlpha aa[], const int16_t runs[]) { @@ -176,7 +178,7 @@ void SkRasterPipelineBlitter::blitAntiH(int x, int y, const SkAlpha aa[], const for (int16_t run = *runs; run > 0; run = *runs) { coverage = *aa * (1/255.0f); - p.run(x, run); + p.compile()(x, run); x += run; runs += run; @@ -210,6 +212,6 @@ void SkRasterPipelineBlitter::blitMask(const SkMask& mask, const SkIRect& clip) } this->append_store(&p, dst); - p.run(x, clip.width()); + p.compile()(x, clip.width()); } } diff --git a/src/opts/SkOpts_hsw.cpp b/src/opts/SkOpts_hsw.cpp index 55fe045a56..8c31af5b83 100644 --- a/src/opts/SkOpts_hsw.cpp +++ b/src/opts/SkOpts_hsw.cpp @@ -12,7 +12,7 @@ namespace SkOpts { void Init_hsw() { - run_pipeline = hsw::run_pipeline; + compile_pipeline = hsw::compile_pipeline; } } diff --git a/src/opts/SkOpts_sse41.cpp b/src/opts/SkOpts_sse41.cpp index 7a90f7683e..0d771bdbef 100644 --- a/src/opts/SkOpts_sse41.cpp +++ b/src/opts/SkOpts_sse41.cpp @@ -20,6 +20,6 @@ namespace SkOpts { box_blur_yx = sse41::box_blur_yx; srcover_srgb_srgb = sse41::srcover_srgb_srgb; blit_row_s32a_opaque = sse41::blit_row_s32a_opaque; - run_pipeline = sse41::run_pipeline; + compile_pipeline = sse41::compile_pipeline; } } diff --git a/src/opts/SkRasterPipeline_opts.h b/src/opts/SkRasterPipeline_opts.h index 2e1e3a2a47..b8c882097e 100644 --- a/src/opts/SkRasterPipeline_opts.h +++ b/src/opts/SkRasterPipeline_opts.h @@ -458,46 +458,47 @@ SI Fn enum_to_Fn(SkRasterPipeline::StockStage st) { namespace SK_OPTS_NS { - SI void run_pipeline(size_t x, size_t n, - const SkRasterPipeline::Stage* stages, int nstages) { - SkASSERT(nstages <= SkRasterPipeline::kMaxStages); - if (nstages == 0) { - return; - } - - SkNf v; // Fastest to start uninitialized. - - if (n >= N) { - BodyStage body[SkRasterPipeline::kMaxStages]; + SI std::function<void(size_t, size_t)> compile_pipeline(const SkRasterPipeline::Stage* stages, + int nstages) { + struct Compiled { + Compiled(const SkRasterPipeline::Stage* stages, int nstages) { + if (nstages == 0) { + return; + } + + fBodyStart = enum_to_Fn<Body>(stages[0].stage); + fTailStart = enum_to_Fn<Tail>(stages[0].stage); + for (int i = 0; i < nstages-1; i++) { + fBody[i].next = enum_to_Fn<Body>(stages[i+1].stage); + fTail[i].next = enum_to_Fn<Tail>(stages[i+1].stage); + fBody[i].ctx = fTail[i].ctx = stages[i].ctx; + } + fBody[nstages-1].next = just_return; + fTail[nstages-1].next = just_return; + fBody[nstages-1].ctx = fTail[nstages-1].ctx = stages[nstages-1].ctx; + } - Body start = enum_to_Fn<Body>(stages[0].stage); - for (int i = 0; i < nstages-1; i++) { - body[i].next = enum_to_Fn<Body>(stages[i+1].stage); - body[i].ctx = stages[i].ctx; + void operator()(size_t x, size_t n) { + SkNf v; // Fastest to start uninitialized. + + while (n >= N) { + fBodyStart(fBody, x, v,v,v,v, v,v,v,v); + x += N; + n -= N; + } + if (n) { + fTailStart(fTail, x,n, v,v,v,v, v,v,v,v); + } } - body[nstages-1].next = just_return; - body[nstages-1].ctx = stages[nstages-1].ctx; - - do { - start(body, x, v,v,v,v, v,v,v,v); - x += N; - n -= N; - } while (n >= N); - } - if (n > 0) { - TailStage tail[SkRasterPipeline::kMaxStages]; + Body fBodyStart = just_return; + Tail fTailStart = just_return; - Tail start = enum_to_Fn<Tail>(stages[0].stage); - for (int i = 0; i < nstages-1; i++) { - tail[i].next = enum_to_Fn<Tail>(stages[i+1].stage); - tail[i].ctx = stages[i].ctx; - } - tail[nstages-1].next = just_return; - tail[nstages-1].ctx = stages[nstages-1].ctx; + BodyStage fBody[SkRasterPipeline::kMaxStages]; + TailStage fTail[SkRasterPipeline::kMaxStages]; - start(tail, x,n, v,v,v,v, v,v,v,v); - } + } fn { stages, nstages }; + return fn; } } // namespace SK_OPTS_NS diff --git a/tests/SkRasterPipelineTest.cpp b/tests/SkRasterPipelineTest.cpp index 76fbc2541c..049729043f 100644 --- a/tests/SkRasterPipelineTest.cpp +++ b/tests/SkRasterPipelineTest.cpp @@ -21,7 +21,7 @@ DEF_TEST(SkRasterPipeline, r) { p.append(SkRasterPipeline::load_d_f16, &red); p.append(SkRasterPipeline::srcover); p.append(SkRasterPipeline::store_f16, &result); - p.run(1); + p.compile()(0, 1); // We should see half-intensity magenta. REPORTER_ASSERT(r, ((result >> 0) & 0xffff) == 0x3800); @@ -33,7 +33,7 @@ DEF_TEST(SkRasterPipeline, r) { DEF_TEST(SkRasterPipeline_empty, r) { // No asserts... just a test that this is safe to run. SkRasterPipeline p; - p.run(20); + p.compile()(0,20); } DEF_TEST(SkRasterPipeline_nonsense, r) { @@ -41,5 +41,5 @@ DEF_TEST(SkRasterPipeline_nonsense, r) { // srcover() calls st->next(); this makes sure we've always got something there to call. SkRasterPipeline p; p.append(SkRasterPipeline::srcover); - p.run(20); + p.compile()(0, 20); } |