skia2/tests/SkRasterPipelineTest.cpp
Mike Klein baaf8ad952 Start moving SkRasterPipeline stages to SkOpts.
This lets them pick up runtime CPU specializations.  Here I've plugged in SSE4.1.  This is still one of the N prelude CLs to full 8-at-a-time AVX.

I've moved the union of the stages used by SkRasterPipelineBench and SkRasterPipelineBlitter to SkOpts... they'll all be used by the blitter eventually.  Picking up SSE4.1 specialization here (even still just 4 pixels at a time) is a significant speedup, especially to store_srgb(), so much that it's no longer really interesting to compare against the fused-but-default-instruction-set version in the bench.  So that's gone now.

That left the SkRasterPipeline unit test as the only other user of the EasyFn simplified interface to SkRasterPipeline.  So I converted that back down to the bare-metal interface, and EasyFn and its friends became SkRasterPipeline_opts.h exclusive abbreviations (now called Kernel_Sk4f).  This isn't really unexpected: SkXfermode also wanted to build up its own little abstractions, and once you build your own abstraction, the value of an additional EasyFn-like layer plummets to negative.

For simplicity I've left the SkXfermode stages alone, except srcover() which was always part of the blitter.  No particular reason except keeping the churn down while I hack.  These _can_ be in SkOpts, but don't have to be until we go 8-at-a-time.

BUG=skia:

GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2752
CQ_INCLUDE_TRYBOTS=master.client.skia:Test-Ubuntu-GCC-GCE-CPU-AVX2-x86_64-Release-SKNX_NO_SIMD-Trybot

Change-Id: I3b476b18232a1598d8977e425be2150059ab71dc
Reviewed-on: https://skia-review.googlesource.com/2752
Reviewed-by: Mike Klein <mtklein@chromium.org>
Commit-Queue: Mike Klein <mtklein@chromium.org>
2016-09-29 16:20:26 +00:00

87 lines
2.8 KiB
C++

/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "Test.h"
#include "SkRasterPipeline.h"
static void SK_VECTORCALL load(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) {
auto ptr = st->ctx<const float*>() + x;
switch(tail&3) {
case 0: a = Sk4f{ptr[3]};
case 3: b = Sk4f{ptr[2]};
case 2: g = Sk4f{ptr[1]};
case 1: r = Sk4f{ptr[0]};
}
st->next(x,tail, r,g,b,a, dr,dg,db,da);
}
static void SK_VECTORCALL square(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) {
r *= r;
g *= g;
b *= b;
a *= a;
st->next(x,tail, r,g,b,a, dr,dg,db,da);
}
static void SK_VECTORCALL store(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) {
auto ptr = st->ctx<float*>() + x;
switch (tail&3) {
case 0: ptr[3] = a[0];
case 3: ptr[2] = b[0];
case 2: ptr[1] = g[0];
case 1: ptr[0] = r[0];
}
}
DEF_TEST(SkRasterPipeline, r) {
// We'll build up and run a simple pipeline that exercises the salient
// mechanics of SkRasterPipeline:
// - context pointers (load,store)
// - stages sensitive to the number of pixels (load,store)
// - stages insensitive to the number of pixels (square)
// - stages that chain to the next stage (load,square)
// - stages that terminate the pipeline (store)
//
// This pipeline loads up some values, squares them, then writes them back to memory.
const float src_vals[] = { 1,2,3,4,5 };
float dst_vals[] = { 0,0,0,0,0 };
SkRasterPipeline p;
p.append(load, src_vals);
p.append(square);
p.append(store, dst_vals);
p.run(5);
REPORTER_ASSERT(r, dst_vals[0] == 1);
REPORTER_ASSERT(r, dst_vals[1] == 4);
REPORTER_ASSERT(r, dst_vals[2] == 9);
REPORTER_ASSERT(r, dst_vals[3] == 16);
REPORTER_ASSERT(r, dst_vals[4] == 25);
}
DEF_TEST(SkRasterPipeline_empty, r) {
// No asserts... just a test that this is safe to run.
SkRasterPipeline p;
p.run(20);
}
DEF_TEST(SkRasterPipeline_nonsense, r) {
// No asserts... just a test that this is safe to run and terminates.
// square() always calls st->next(); this makes sure we've always got something there to call.
SkRasterPipeline p;
p.append(square);
p.run(20);
}