skia2/bench/SkRasterPipelineBench.cpp

171 lines
5.4 KiB
C++
Raw Normal View History

/*
* 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 "Benchmark.h"
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 13:04:15 +00:00
#include "SkOpts.h"
#include "SkRasterPipeline.h"
#include "../src/jumper/SkJumper.h"
static const int N = 15;
static uint64_t dst[N]; // sRGB or F16
static uint32_t src[N]; // sRGB
static uint8_t mask[N]; // 8-bit linear
// We'll build up a somewhat realistic useful pipeline:
// - load srgb src
// - scale src by 8-bit mask
// - load srgb/f16 dst
// - src = srcover(dst, src)
// - store src back as srgb/f16
template <bool kF16>
class SkRasterPipelineBench : public Benchmark {
public:
bool isSuitableFor(Backend backend) override { return backend == kNonRendering_Backend; }
const char* onGetName() override {
switch ((int)kF16) {
case 0: return "SkRasterPipeline_srgb";
case 1: return "SkRasterPipeline_f16";
}
return "whoops";
}
void onDraw(int loops, SkCanvas*) override {
SkJumper_MemoryCtx mask_ctx = {mask, 0},
src_ctx = {src, 0},
dst_ctx = {dst, 0};
SkRasterPipeline_<256> p;
p.append(SkRasterPipeline::load_8888, &src_ctx);
p.append(SkRasterPipeline::from_srgb);
p.append(SkRasterPipeline::scale_u8, &mask_ctx);
p.append(SkRasterPipeline::move_src_dst);
if (kF16) {
p.append(SkRasterPipeline::load_f16, &dst_ctx);
} else {
p.append(SkRasterPipeline::load_8888, &dst_ctx);
p.append(SkRasterPipeline::from_srgb);
}
p.append(SkRasterPipeline::dstover);
if (kF16) {
p.append(SkRasterPipeline::store_f16, &dst_ctx);
} else {
p.append(SkRasterPipeline::to_srgb);
p.append(SkRasterPipeline::store_8888, &dst_ctx);
}
while (loops --> 0) {
p.run(0,0,N,1);
}
}
};
DEF_BENCH( return (new SkRasterPipelineBench< true>); )
DEF_BENCH( return (new SkRasterPipelineBench<false>); )
class SkRasterPipelineCompileVsRunBench : public Benchmark {
public:
explicit SkRasterPipelineCompileVsRunBench(bool compile) : fCompile(compile) {}
bool isSuitableFor(Backend backend) override { return backend == kNonRendering_Backend; }
const char* onGetName() override {
return fCompile ? "SkRasterPipeline_compile"
: "SkRasterPipeline_run";
}
void onDraw(int loops, SkCanvas*) override {
SkJumper_MemoryCtx src_ctx = {src, 0},
dst_ctx = {dst, 0};
SkRasterPipeline_<256> p;
p.append(SkRasterPipeline::load_8888, &dst_ctx);
p.append(SkRasterPipeline::move_src_dst);
p.append(SkRasterPipeline::load_8888, &src_ctx);
p.append(SkRasterPipeline::srcover);
p.append(SkRasterPipeline::store_8888, &dst_ctx);
if (fCompile) {
auto fn = p.compile();
while (loops --> 0) {
fn(0,0,N,1);
}
} else {
while (loops --> 0) {
p.run(0,0,N,1);
}
}
}
private:
bool fCompile;
};
DEF_BENCH( return (new SkRasterPipelineCompileVsRunBench(true )); )
DEF_BENCH( return (new SkRasterPipelineCompileVsRunBench(false)); )
static SkColorSpaceTransferFn gamma(float g) {
SkColorSpaceTransferFn fn = {0,0,0,0,0,0,0};
fn.fG = g;
fn.fA = 1;
return fn;
}
class SkRasterPipeline_2dot2 : public Benchmark {
public:
SkRasterPipeline_2dot2(bool parametric) : fParametric(parametric) {}
bool isSuitableFor(Backend backend) override { return backend == kNonRendering_Backend; }
const char* onGetName() override {
return fParametric ? "SkRasterPipeline_2dot2_parametric"
: "SkRasterPipeline_2dot2_gamma";
}
void onDraw(int loops, SkCanvas*) override {
SkColor4f c = { 1.0f, 1.0f, 1.0f, 1.0f };
SkColorSpaceTransferFn from_2dot2 = gamma( 2.2f),
to_2dot2 = gamma(1/2.2f);
SkSTArenaAlloc<256> alloc;
SkRasterPipeline p(&alloc);
p.append_constant_color(&alloc, c);
if (fParametric) {
p.append(SkRasterPipeline::parametric_r, &from_2dot2);
p.append(SkRasterPipeline::parametric_g, &from_2dot2);
p.append(SkRasterPipeline::parametric_b, &from_2dot2);
p.append(SkRasterPipeline::parametric_r, & to_2dot2);
p.append(SkRasterPipeline::parametric_g, & to_2dot2);
p.append(SkRasterPipeline::parametric_b, & to_2dot2);
} else {
p.append(SkRasterPipeline::gamma, &from_2dot2.fG);
p.append(SkRasterPipeline::gamma, & to_2dot2.fG);
}
while (loops --> 0) {
p.run(0,0,N,1);
}
}
private:
bool fParametric;
};
DEF_BENCH( return (new SkRasterPipeline_2dot2( true)); )
DEF_BENCH( return (new SkRasterPipeline_2dot2(false)); )
class SkRasterPipelineToSRGB : public Benchmark {
public:
bool isSuitableFor(Backend backend) override { return backend == kNonRendering_Backend; }
const char* onGetName() override {
return "SkRasterPipeline_to_srgb";
}
void onDraw(int loops, SkCanvas*) override {
SkRasterPipeline_<256> p;
p.append(SkRasterPipeline::to_srgb);
while (loops --> 0) {
p.run(0,0,N,1);
}
}
};
DEF_BENCH( return (new SkRasterPipelineToSRGB); )