Simplify more: remove SkRasterPipeline::compile().
It's easier to work on SkJumper if everything funnels through run(). I don't anticipate huge benefit from compile() without JITing, but it's something we can always put back if we find a need. Change-Id: Id5256fd21495e8195cad1924dbad81856416d913 Reviewed-on: https://skia-review.googlesource.com/8468 Commit-Queue: Mike Klein <mtklein@chromium.org> Reviewed-by: Mike Klein <mtklein@chromium.org>
This commit is contained in:
parent
394d414452
commit
8729e5bbf7
@ -22,16 +22,14 @@ static uint8_t mask[N]; // 8-bit linear
|
||||
// - src = srcover(dst, src)
|
||||
// - store src back as srgb/f16
|
||||
|
||||
template <bool kF16, bool kCompiled>
|
||||
template <bool kF16>
|
||||
class SkRasterPipelineBench : public Benchmark {
|
||||
public:
|
||||
bool isSuitableFor(Backend backend) override { return backend == kNonRendering_Backend; }
|
||||
const char* onGetName() override {
|
||||
switch ((int)kCompiled << 1 | (int)kF16) {
|
||||
case 0: return "SkRasterPipeline_srgb_run";
|
||||
case 1: return "SkRasterPipeline_f16_run";
|
||||
case 2: return "SkRasterPipeline_srgb_compile";
|
||||
case 3: return "SkRasterPipeline_f16_compile";
|
||||
switch ((int)kF16) {
|
||||
case 0: return "SkRasterPipeline_srgb";
|
||||
case 1: return "SkRasterPipeline_f16";
|
||||
}
|
||||
return "whoops";
|
||||
}
|
||||
@ -60,30 +58,19 @@ public:
|
||||
p.append(SkRasterPipeline::store_8888, &dst_ctx);
|
||||
}
|
||||
|
||||
if (kCompiled) {
|
||||
auto compiled = p.compile();
|
||||
while (loops --> 0) {
|
||||
compiled(0,N);
|
||||
}
|
||||
} else {
|
||||
while (loops --> 0) {
|
||||
p.run(0,N);
|
||||
}
|
||||
while (loops --> 0) {
|
||||
p.run(0,N);
|
||||
}
|
||||
}
|
||||
};
|
||||
DEF_BENCH( return (new SkRasterPipelineBench< true, true>); )
|
||||
DEF_BENCH( return (new SkRasterPipelineBench<false, true>); )
|
||||
DEF_BENCH( return (new SkRasterPipelineBench< true, false>); )
|
||||
DEF_BENCH( return (new SkRasterPipelineBench<false, false>); )
|
||||
DEF_BENCH( return (new SkRasterPipelineBench< true>); )
|
||||
DEF_BENCH( return (new SkRasterPipelineBench<false>); )
|
||||
|
||||
template <bool kCompiled>
|
||||
class SkRasterPipelineLegacyBench : public Benchmark {
|
||||
public:
|
||||
bool isSuitableFor(Backend backend) override { return backend == kNonRendering_Backend; }
|
||||
const char* onGetName() override {
|
||||
return kCompiled ? "SkRasterPipeline_legacy_compile"
|
||||
: "SkRasterPipeline_legacy_run";
|
||||
return "SkRasterPipeline_legacy";
|
||||
}
|
||||
|
||||
void onDraw(int loops, SkCanvas*) override {
|
||||
@ -97,17 +84,9 @@ public:
|
||||
p.append(SkRasterPipeline::srcover);
|
||||
p.append(SkRasterPipeline::store_8888, &dst_ctx);
|
||||
|
||||
if (kCompiled) {
|
||||
auto compiled = p.compile();
|
||||
while (loops --> 0) {
|
||||
compiled(0,N);
|
||||
}
|
||||
} else {
|
||||
while (loops --> 0) {
|
||||
p.run(0,N);
|
||||
}
|
||||
while (loops --> 0) {
|
||||
p.run(0,N);
|
||||
}
|
||||
}
|
||||
};
|
||||
DEF_BENCH( return (new SkRasterPipelineLegacyBench< true>); )
|
||||
DEF_BENCH( return (new SkRasterPipelineLegacyBench<false>); )
|
||||
DEF_BENCH( return (new SkRasterPipelineLegacyBench); )
|
||||
|
@ -275,10 +275,8 @@ static void convert_with_pipeline(const SkImageInfo& dstInfo, void* dstRow, size
|
||||
break;
|
||||
}
|
||||
|
||||
auto p = pipeline.compile();
|
||||
|
||||
for (int y = 0; y < srcInfo.height(); ++y) {
|
||||
p(0,srcInfo.width());
|
||||
pipeline.run(0,srcInfo.width());
|
||||
// The pipeline has pointers to srcRow and dstRow, so we just need to update them in the
|
||||
// loop to move between rows of src/dst.
|
||||
dstRow = SkTAddOffset<void>(dstRow, dstRB);
|
||||
|
@ -85,7 +85,6 @@ namespace SkOpts {
|
||||
DEFINE_DEFAULT(hash_fn);
|
||||
|
||||
DEFINE_DEFAULT(run_pipeline);
|
||||
DEFINE_DEFAULT(compile_pipeline);
|
||||
|
||||
DEFINE_DEFAULT(convolve_vertically);
|
||||
DEFINE_DEFAULT(convolve_horizontally);
|
||||
|
@ -12,7 +12,6 @@
|
||||
#include "SkRasterPipeline.h"
|
||||
#include "SkTypes.h"
|
||||
#include "SkXfermodePriv.h"
|
||||
#include <functional>
|
||||
|
||||
struct ProcCoeff;
|
||||
|
||||
@ -61,8 +60,6 @@ namespace SkOpts {
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
extern void (*convolve_vertically)(const SkConvolutionFilter1D::ConvolutionFixed* filter_values,
|
||||
int filter_length, unsigned char* const* source_data_rows,
|
||||
|
@ -31,10 +31,6 @@ void SkRasterPipeline::run(size_t x, size_t n) const {
|
||||
}
|
||||
}
|
||||
|
||||
std::function<void(size_t, size_t)> SkRasterPipeline::compile() const {
|
||||
return SkOpts::compile_pipeline(fStages.data(), SkToInt(fStages.size()));
|
||||
}
|
||||
|
||||
void SkRasterPipeline::dump() const {
|
||||
SkDebugf("SkRasterPipeline, %d stages\n", SkToInt(fStages.size()));
|
||||
for (auto&& st : fStages) {
|
||||
|
@ -12,7 +12,6 @@
|
||||
#include "SkNx.h"
|
||||
#include "SkTArray.h"
|
||||
#include "SkTypes.h"
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
@ -120,9 +119,6 @@ public:
|
||||
// Runs the pipeline walking x through [x,x+n).
|
||||
void run(size_t x, size_t n) const;
|
||||
|
||||
// If you're going to run() the pipeline more than once, it's best to compile it.
|
||||
std::function<void(size_t x, size_t n)> compile() const;
|
||||
|
||||
void dump() const;
|
||||
|
||||
struct Stage {
|
||||
@ -134,6 +130,8 @@ public:
|
||||
// Use these helpers to keep things sane.
|
||||
void append_from_srgb(SkAlphaType);
|
||||
|
||||
bool empty() const { return fStages.empty(); }
|
||||
|
||||
private:
|
||||
bool run_with_jumper(size_t x, size_t n) const;
|
||||
|
||||
|
@ -50,14 +50,18 @@ private:
|
||||
SkRasterPipeline fShader;
|
||||
bool fBlendCorrectly;
|
||||
|
||||
// These functions are compiled lazily when first used.
|
||||
std::function<void(size_t, size_t)> fBlitH = nullptr,
|
||||
fBlitAntiH = nullptr,
|
||||
fBlitMaskA8 = nullptr,
|
||||
fBlitMaskLCD16 = nullptr;
|
||||
// We may be able to specialize blitH() into a memset.
|
||||
bool fCanMemsetInBlitH = false;
|
||||
uint64_t fMemsetColor = 0; // Big enough for largest dst format, F16.
|
||||
|
||||
// These values are pointed to by the compiled blit functions
|
||||
// above, which allows us to adjust them from call to call.
|
||||
// Built lazily on first use.
|
||||
SkRasterPipeline fBlitH,
|
||||
fBlitAntiH,
|
||||
fBlitMaskA8,
|
||||
fBlitMaskLCD16;
|
||||
|
||||
// These values are pointed to by the blit pipelines above,
|
||||
// which allows us to adjust them from call to call.
|
||||
void* fDstPtr = nullptr;
|
||||
const void* fMaskPtr = nullptr;
|
||||
float fCurrentCoverage = 0.0f;
|
||||
@ -152,31 +156,13 @@ SkBlitter* SkRasterPipelineBlitter::Create(const SkPixmap& dst,
|
||||
}
|
||||
|
||||
if (is_constant && *blend == SkBlendMode::kSrc) {
|
||||
uint64_t color; // Big enough for largest dst format, F16.
|
||||
SkRasterPipeline p;
|
||||
p.extend(*pipeline);
|
||||
blitter->fDstPtr = &color;
|
||||
blitter->fDstPtr = &blitter->fMemsetColor;
|
||||
blitter->append_store(&p);
|
||||
p.run(0,1);
|
||||
|
||||
switch (dst.shiftPerPixel()) {
|
||||
case 1:
|
||||
blitter->fBlitH = [blitter,color](size_t x, size_t n) {
|
||||
sk_memset16((uint16_t*)blitter->fDstPtr + x, color, n);
|
||||
};
|
||||
break;
|
||||
case 2:
|
||||
blitter->fBlitH = [blitter,color](size_t x, size_t n) {
|
||||
sk_memset32((uint32_t*)blitter->fDstPtr + x, color, n);
|
||||
};
|
||||
break;
|
||||
case 3:
|
||||
blitter->fBlitH = [blitter,color](size_t x, size_t n) {
|
||||
sk_memset64((uint64_t*)blitter->fDstPtr + x, color, n);
|
||||
};
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
blitter->fCanMemsetInBlitH = true;
|
||||
}
|
||||
|
||||
return blitter;
|
||||
@ -233,8 +219,27 @@ void SkRasterPipelineBlitter::maybe_clamp(SkRasterPipeline* p) const {
|
||||
}
|
||||
|
||||
void SkRasterPipelineBlitter::blitH(int x, int y, int w) {
|
||||
if (!fBlitH) {
|
||||
SkRasterPipeline p;
|
||||
fDstPtr = fDst.writable_addr(0,y);
|
||||
fCurrentY = y;
|
||||
|
||||
if (fCanMemsetInBlitH) {
|
||||
switch (fDst.shiftPerPixel()) {
|
||||
// TODO: case 0: memset (for A8)
|
||||
case 1:
|
||||
sk_memset16((uint16_t*)fDstPtr + x, fMemsetColor, w);
|
||||
return;
|
||||
case 2:
|
||||
sk_memset32((uint32_t*)fDstPtr + x, fMemsetColor, w);
|
||||
return;
|
||||
case 3:
|
||||
sk_memset64((uint64_t*)fDstPtr + x, fMemsetColor, w);
|
||||
return;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
auto& p = fBlitH;
|
||||
if (p.empty()) {
|
||||
p.extend(fShader);
|
||||
if (fBlend != SkBlendMode::kSrc) {
|
||||
this->append_load_d(&p);
|
||||
@ -242,16 +247,13 @@ void SkRasterPipelineBlitter::blitH(int x, int y, int w) {
|
||||
this->maybe_clamp(&p);
|
||||
}
|
||||
this->append_store(&p);
|
||||
fBlitH = p.compile();
|
||||
}
|
||||
fDstPtr = fDst.writable_addr(0,y);
|
||||
fCurrentY = y;
|
||||
fBlitH(x,w);
|
||||
p.run(x,w);
|
||||
}
|
||||
|
||||
void SkRasterPipelineBlitter::blitAntiH(int x, int y, const SkAlpha aa[], const int16_t runs[]) {
|
||||
if (!fBlitAntiH) {
|
||||
SkRasterPipeline p;
|
||||
auto& p = fBlitAntiH;
|
||||
if (p.empty()) {
|
||||
p.extend(fShader);
|
||||
if (fBlend == SkBlendMode::kSrcOver) {
|
||||
p.append(SkRasterPipeline::scale_1_float, &fCurrentCoverage);
|
||||
@ -264,7 +266,6 @@ void SkRasterPipelineBlitter::blitAntiH(int x, int y, const SkAlpha aa[], const
|
||||
}
|
||||
this->maybe_clamp(&p);
|
||||
this->append_store(&p);
|
||||
fBlitAntiH = p.compile();
|
||||
}
|
||||
|
||||
fDstPtr = fDst.writable_addr(0,y);
|
||||
@ -275,7 +276,7 @@ void SkRasterPipelineBlitter::blitAntiH(int x, int y, const SkAlpha aa[], const
|
||||
case 0xff: this->blitH(x,y,run); break;
|
||||
default:
|
||||
fCurrentCoverage = *aa * (1/255.0f);
|
||||
fBlitAntiH(x,run);
|
||||
p.run(x,run);
|
||||
}
|
||||
x += run;
|
||||
runs += run;
|
||||
@ -289,8 +290,8 @@ void SkRasterPipelineBlitter::blitMask(const SkMask& mask, const SkIRect& clip)
|
||||
return INHERITED::blitMask(mask, clip);
|
||||
}
|
||||
|
||||
if (mask.fFormat == SkMask::kA8_Format && !fBlitMaskA8) {
|
||||
SkRasterPipeline p;
|
||||
if (mask.fFormat == SkMask::kA8_Format && fBlitMaskA8.empty()) {
|
||||
auto& p = fBlitMaskA8;
|
||||
p.extend(fShader);
|
||||
if (fBlend == SkBlendMode::kSrcOver) {
|
||||
p.append(SkRasterPipeline::scale_u8, &fMaskPtr);
|
||||
@ -303,18 +304,16 @@ void SkRasterPipelineBlitter::blitMask(const SkMask& mask, const SkIRect& clip)
|
||||
}
|
||||
this->maybe_clamp(&p);
|
||||
this->append_store(&p);
|
||||
fBlitMaskA8 = p.compile();
|
||||
}
|
||||
|
||||
if (mask.fFormat == SkMask::kLCD16_Format && !fBlitMaskLCD16) {
|
||||
SkRasterPipeline p;
|
||||
if (mask.fFormat == SkMask::kLCD16_Format && fBlitMaskLCD16.empty()) {
|
||||
auto& p = fBlitMaskLCD16;
|
||||
p.extend(fShader);
|
||||
this->append_load_d(&p);
|
||||
this->append_blend(&p);
|
||||
p.append(SkRasterPipeline::lerp_565, &fMaskPtr);
|
||||
this->maybe_clamp(&p);
|
||||
this->append_store(&p);
|
||||
fBlitMaskLCD16 = p.compile();
|
||||
}
|
||||
|
||||
int x = clip.left();
|
||||
@ -325,11 +324,11 @@ void SkRasterPipelineBlitter::blitMask(const SkMask& mask, const SkIRect& clip)
|
||||
switch (mask.fFormat) {
|
||||
case SkMask::kA8_Format:
|
||||
fMaskPtr = mask.getAddr8(x,y)-x;
|
||||
fBlitMaskA8(x,clip.width());
|
||||
fBlitMaskA8.run(x,clip.width());
|
||||
break;
|
||||
case SkMask::kLCD16_Format:
|
||||
fMaskPtr = mask.getAddrLCD16(x,y)-x;
|
||||
fBlitMaskLCD16(x,clip.width());
|
||||
fBlitMaskLCD16.run(x,clip.width());
|
||||
break;
|
||||
default:
|
||||
// TODO
|
||||
|
@ -21,6 +21,5 @@ namespace SkOpts {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -1221,11 +1221,6 @@ namespace {
|
||||
|
||||
namespace SK_OPTS_NS {
|
||||
|
||||
SI std::function<void(size_t, size_t)>
|
||||
compile_pipeline(const SkRasterPipeline::Stage* stages, int nstages) {
|
||||
return Compiled{stages,nstages};
|
||||
}
|
||||
|
||||
SI void run_pipeline(size_t x, size_t n,
|
||||
const SkRasterPipeline::Stage* stages, int nstages) {
|
||||
static const int kStackMax = 256;
|
||||
|
@ -34,16 +34,6 @@ DEF_TEST(SkRasterPipeline, r) {
|
||||
REPORTER_ASSERT(r, ((result >> 16) & 0xffff) == 0x0000);
|
||||
REPORTER_ASSERT(r, ((result >> 32) & 0xffff) == 0x3800);
|
||||
REPORTER_ASSERT(r, ((result >> 48) & 0xffff) == 0x3c00);
|
||||
|
||||
// Run again, this time compiling the pipeline.
|
||||
result = 0;
|
||||
|
||||
auto fn = p.compile();
|
||||
fn(0,1);
|
||||
REPORTER_ASSERT(r, ((result >> 0) & 0xffff) == 0x3800);
|
||||
REPORTER_ASSERT(r, ((result >> 16) & 0xffff) == 0x0000);
|
||||
REPORTER_ASSERT(r, ((result >> 32) & 0xffff) == 0x3800);
|
||||
REPORTER_ASSERT(r, ((result >> 48) & 0xffff) == 0x3c00);
|
||||
}
|
||||
|
||||
DEF_TEST(SkRasterPipeline_empty, r) {
|
||||
@ -79,8 +69,7 @@ DEF_TEST(SkRasterPipeline_JIT, r) {
|
||||
SkRasterPipeline p;
|
||||
p.append(SkRasterPipeline:: load_8888, &src);
|
||||
p.append(SkRasterPipeline::store_8888, &dst);
|
||||
auto fn = p.compile();
|
||||
fn(15, 20);
|
||||
p.run(15, 20);
|
||||
|
||||
for (int i = 0; i < 36; i++) {
|
||||
if (i < 15 || i == 35) {
|
||||
|
Loading…
Reference in New Issue
Block a user