diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/core/SkRasterPipeline.cpp | 6 | ||||
-rw-r--r-- | src/core/SkRasterPipeline.h | 2 | ||||
-rw-r--r-- | src/opts/SkXbyak.cpp | 97 |
3 files changed, 105 insertions, 0 deletions
diff --git a/src/core/SkRasterPipeline.cpp b/src/core/SkRasterPipeline.cpp index 7b3d49d413..8d0840f7fb 100644 --- a/src/core/SkRasterPipeline.cpp +++ b/src/core/SkRasterPipeline.cpp @@ -27,6 +27,12 @@ void SkRasterPipeline::run(size_t x, size_t y, size_t n) const { } std::function<void(size_t, size_t, size_t)> SkRasterPipeline::compile() const { +#ifdef SK_XBYAK + if (auto fn = this->jit()) { + SkDebugf("Jitted with xbyak!\n"); + return fn; + } +#endif return SkOpts::compile_pipeline(fStages.data(), SkToInt(fStages.size())); } diff --git a/src/core/SkRasterPipeline.h b/src/core/SkRasterPipeline.h index e6c99159fa..b73f62631d 100644 --- a/src/core/SkRasterPipeline.h +++ b/src/core/SkRasterPipeline.h @@ -126,6 +126,8 @@ public: void append_from_srgb(SkAlphaType); private: + std::function<void(size_t, size_t, size_t)> jit() const; + std::vector<Stage> fStages; }; diff --git a/src/opts/SkXbyak.cpp b/src/opts/SkXbyak.cpp new file mode 100644 index 0000000000..12f5200939 --- /dev/null +++ b/src/opts/SkXbyak.cpp @@ -0,0 +1,97 @@ +/* + * 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 "SkCpu.h" +#include "SkRasterPipeline.h" +#include <memory> + +#if defined(__clang__) + #pragma clang diagnostic ignored "-Wduplicate-enum" +#endif +#define XBYAK_NO_OP_NAMES // xor(), not(), etc. -> xor_(), not_(), etc. +#include "xbyak/xbyak.h" + +namespace { + + struct Pipeline : public Xbyak::CodeGenerator { + + static std::shared_ptr<Pipeline> Create(const SkRasterPipeline::Stage* stages, int n) { + if (!SkCpu::Supports(SkCpu::HSW)) { + // TODO: other targets? + return nullptr; + } + + bool supported = true; + auto pipeline = std::make_shared<Pipeline>(stages, n, &supported); + if (supported) { + return pipeline; + } + return nullptr; + } + + Pipeline(const SkRasterPipeline::Stage* stages, int n, bool* supported) { + // Set up some register name aliases. + //auto x = rdi, y = rsi, tail = rdx; + auto r = ymm0, g = ymm1, b = ymm2, a = ymm3, + dr = ymm4, dg = ymm5, db = ymm6, da = ymm7; + + Xbyak::Label floatOneStorage; + vbroadcastss(ymm8, ptr[rip + floatOneStorage]); + + // TODO: set up (x+0.5,y+0.5) in (r,g) + vxorps(r,r); + vxorps(g,g); + vxorps(b,b); + vxorps(a,a); + vxorps(dr,dr); + vxorps(dg,dg); + vxorps(db,db); + vxorps(da,da); + + for (int i = 0; i < n; i++) { + switch(stages[i].stage) { + + default: + *supported = false; + return; + } + } + + ret(); + L(floatOneStorage); df(1.0f); + } + + void df(float f) { + union { float f; uint32_t x; } pun = {f}; + dd(pun.x); + } + }; + +} // namespace + +std::function<void(size_t, size_t, size_t)> SkRasterPipeline::jit() const { + try { + if (auto pipeline = Pipeline::Create(fStages.data(), SkToInt(fStages.size()))) { + return [pipeline] (size_t x, size_t y, size_t n) { + auto call = pipeline->getCode<void(*)(size_t, size_t, size_t)>(); + while (n >= 8) { + call(x,y,0); + x += 8; + n -= 8; + } + if (n) { + call(x,y,n); + } + }; + } + SkDebugf("Cannot yet JIT with xbyak:\n"); + this->dump(); + return nullptr; + } catch(...) { + return nullptr; + } +} |