From 7f71d8845c3c57c6e4b33c3666cca46b55e91d02 Mon Sep 17 00:00:00 2001 From: Mike Klein Date: Fri, 6 Jan 2017 12:00:31 -0500 Subject: SkXbyak basics A little JIT proof of concept for SkRasterPipeline, using xbyak, which is a header-only assembler. It's x86-only, but supports x86 very thoroughly, and it's very user friendly (at least as far as assembler libraries go...). CQ_INCLUDE_TRYBOTS=skia.primary:Test-Ubuntu-GCC-GCE-CPU-AVX2-x86_64-Release-SKNX_NO_SIMD Change-Id: Ie17e562b0f3fff5914041badfb2c1fe4f86efab8 Reviewed-on: https://skia-review.googlesource.com/5730 Reviewed-by: Herb Derby Reviewed-by: Heather Miller Commit-Queue: Mike Klein --- src/opts/SkXbyak.cpp | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 src/opts/SkXbyak.cpp (limited to 'src/opts/SkXbyak.cpp') 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 + +#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 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(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 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(); + 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; + } +} -- cgit v1.2.3