1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
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;
}
}
|