aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--BUILD.gn18
-rw-r--r--DEPS3
-rw-r--r--src/core/SkRasterPipeline.cpp6
-rw-r--r--src/core/SkRasterPipeline.h2
-rw-r--r--src/opts/SkXbyak.cpp97
-rw-r--r--tests/SkRasterPipelineTest.cpp10
-rw-r--r--third_party/xbyak/BUILD.gn13
7 files changed, 149 insertions, 0 deletions
diff --git a/BUILD.gn b/BUILD.gn
index 2c9335cca1..82751cf3d0 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -23,6 +23,7 @@ declare_args() {
skia_use_lua = false
skia_use_mesa = false
skia_use_piex = !is_win
+ skia_use_xbyak = false
skia_use_zlib = true
skia_android_serial = ""
@@ -506,6 +507,22 @@ optional("webp") {
]
}
+optional("xbyak") {
+ enabled = skia_use_xbyak
+ public_defines = [ "SK_XBYAK" ]
+
+ deps = [
+ "//third_party/xbyak",
+ ]
+
+ # xbyak uses exceptions, but SkXbyak catches them all.
+ configs_to_remove = [ "//gn:no_exceptions" ]
+
+ sources = [
+ "src/opts/SkXbyak.cpp",
+ ]
+}
+
optional("xml") {
enabled = skia_use_expat
public_defines = [ "SK_XML" ]
@@ -546,6 +563,7 @@ component("skia") {
":ssse3",
":typeface_freetype",
":webp",
+ ":xbyak",
":xml",
]
diff --git a/DEPS b/DEPS
index 60c7ce921a..0eb3193119 100644
--- a/DEPS
+++ b/DEPS
@@ -42,6 +42,9 @@ deps = {
# microhttpd for skiaserve
"third_party/externals/microhttpd" : "https://android.googlesource.com/platform/external/libmicrohttpd@748945ec6f1c67b7efc934ab0808e1d32f2fb98d",
+
+ # TODO: mirror to skia.googlesource.com
+ "third_party/externals/xbyak" : "https://github.com/herumi/xbyak",
}
recursedeps = [ "common" ]
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;
+ }
+}
diff --git a/tests/SkRasterPipelineTest.cpp b/tests/SkRasterPipelineTest.cpp
index ddd84e7cce..2f9b4066b5 100644
--- a/tests/SkRasterPipelineTest.cpp
+++ b/tests/SkRasterPipelineTest.cpp
@@ -34,6 +34,16 @@ 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,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) {
diff --git a/third_party/xbyak/BUILD.gn b/third_party/xbyak/BUILD.gn
new file mode 100644
index 0000000000..7595c32f2c
--- /dev/null
+++ b/third_party/xbyak/BUILD.gn
@@ -0,0 +1,13 @@
+# Copyright 2016 Google Inc.
+#
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+declare_args() {
+}
+
+import("../third_party.gni")
+
+third_party("xbyak") {
+ public_include_dirs = [ "../externals/xbyak/" ]
+}