Add ceil to skvx/skvm/JIT, and floor/ceil intrinsics to ByteCode
This is enough to get the colorcube GM working on the CPU backend. (It's not blazingly fast, but it works!) Change-Id: Ic069861bab162ed49f876fd03af2cbaaec2da628 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/297718 Reviewed-by: Mike Klein <mtklein@google.com> Commit-Queue: Brian Osman <brianosman@google.com>
This commit is contained in:
parent
df4e3ab185
commit
89bf734d87
@ -279,12 +279,7 @@ class ColorCubeRT : public skiagm::GM {
|
||||
|
||||
SkISize onISize() override { return {512, 512}; }
|
||||
|
||||
DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
|
||||
if (canvas->getGrContext() == nullptr) {
|
||||
// until SkSL can handle child processors on the raster backend
|
||||
return DrawResult::kSkip;
|
||||
}
|
||||
|
||||
void onDraw(SkCanvas* canvas) override {
|
||||
// First we draw the unmodified image, and a copy that was sepia-toned in Photoshop:
|
||||
canvas->drawImage(fMandrill, 0, 0);
|
||||
canvas->drawImage(fMandrillSepia, 0, 256);
|
||||
@ -319,8 +314,6 @@ class ColorCubeRT : public skiagm::GM {
|
||||
paint.setShader(builder.makeShader(nullptr, true));
|
||||
canvas->translate(0, 256);
|
||||
canvas->drawRect({ 0, 0, 256, 256 }, paint);
|
||||
|
||||
return DrawResult::kOk;
|
||||
}
|
||||
};
|
||||
DEF_GM(return new ColorCubeRT;)
|
||||
|
@ -673,6 +673,16 @@ static std::vector<skvm::F32> program_fn(skvm::Builder* p,
|
||||
case Inst::kATan3:
|
||||
case Inst::kATan4: unary(Inst::kATan, skvm::approx_atan); break;
|
||||
|
||||
case Inst::kCeil:
|
||||
case Inst::kCeil2:
|
||||
case Inst::kCeil3:
|
||||
case Inst::kCeil4: unary(Inst::kCeil, skvm::ceil); break;
|
||||
|
||||
case Inst::kFloor:
|
||||
case Inst::kFloor2:
|
||||
case Inst::kFloor3:
|
||||
case Inst::kFloor4: unary(Inst::kFloor, skvm::floor); break;
|
||||
|
||||
case Inst::kFract:
|
||||
case Inst::kFract2:
|
||||
case Inst::kFract3:
|
||||
|
@ -250,6 +250,7 @@ namespace skvm {
|
||||
case Op::select: write(o, V{id}, "=", op, V{x}, V{y}, V{z}, fs(id)...); break;
|
||||
case Op::pack: write(o, V{id}, "=", op, V{x}, V{y}, Shift{immz}, fs(id)...); break;
|
||||
|
||||
case Op::ceil: write(o, V{id}, "=", op, V{x}, fs(id)...); break;
|
||||
case Op::floor: write(o, V{id}, "=", op, V{x}, fs(id)...); break;
|
||||
case Op::to_f32: write(o, V{id}, "=", op, V{x}, fs(id)...); break;
|
||||
case Op::trunc: write(o, V{id}, "=", op, V{x}, fs(id)...); break;
|
||||
@ -369,6 +370,7 @@ namespace skvm {
|
||||
case Op::select: write(o, R{d}, "=", op, R{x}, R{y}, R{z}); break;
|
||||
case Op::pack: write(o, R{d}, "=", op, R{x}, R{y}, Shift{immz}); break;
|
||||
|
||||
case Op::ceil: write(o, R{d}, "=", op, R{x}); break;
|
||||
case Op::floor: write(o, R{d}, "=", op, R{x}); break;
|
||||
case Op::to_f32: write(o, R{d}, "=", op, R{x}); break;
|
||||
case Op::trunc: write(o, R{d}, "=", op, R{x}); break;
|
||||
@ -1013,6 +1015,10 @@ namespace skvm {
|
||||
return {this, this->push(Op::pack, x.id,y.id,NA, 0,bits)};
|
||||
}
|
||||
|
||||
F32 Builder::ceil(F32 x) {
|
||||
if (float X; this->allImm(x.id,&X)) { return splat(ceilf(X)); }
|
||||
return {this, this->push(Op::ceil, x.id)};
|
||||
}
|
||||
F32 Builder::floor(F32 x) {
|
||||
if (float X; this->allImm(x.id,&X)) { return splat(floorf(X)); }
|
||||
return {this, this->push(Op::floor, x.id)};
|
||||
@ -2352,6 +2358,9 @@ namespace skvm {
|
||||
F(vals[z])}));
|
||||
break;
|
||||
|
||||
case Op::ceil:
|
||||
vals[i] = I(b->CreateUnaryIntrinsic(llvm::Intrinsic::ceil, F(vals[x])));
|
||||
break;
|
||||
case Op::floor:
|
||||
vals[i] = I(b->CreateUnaryIntrinsic(llvm::Intrinsic::floor, F(vals[x])));
|
||||
break;
|
||||
@ -3223,6 +3232,11 @@ namespace skvm {
|
||||
a->vpor (dst(), dst(), any(x));
|
||||
break;
|
||||
|
||||
case Op::ceil:
|
||||
if (in_reg(x)) { a->vroundps(dst(x), r(x), Assembler::CEIL); }
|
||||
else { a->vroundps(dst(), any(x), Assembler::CEIL); }
|
||||
break;
|
||||
|
||||
case Op::floor:
|
||||
if (in_reg(x)) { a->vroundps(dst(x), r(x), Assembler::FLOOR); }
|
||||
else { a->vroundps(dst(), any(x), Assembler::FLOOR); }
|
||||
|
@ -387,7 +387,8 @@ namespace skvm {
|
||||
M(fma_f32) M(fms_f32) M(fnma_f32) \
|
||||
M(sqrt_f32) \
|
||||
M(shl_i32) M(shr_i32) M(sra_i32) \
|
||||
M(floor) M(trunc) M(round) M(to_f32) \
|
||||
M(ceil) M(floor) M(trunc) M(round) \
|
||||
M(to_f32) \
|
||||
M( eq_f32) M( eq_i32) \
|
||||
M(neq_f32) \
|
||||
M( gt_f32) M( gt_i32) \
|
||||
@ -642,6 +643,7 @@ namespace skvm {
|
||||
|
||||
F32 abs(F32 x) { return bit_cast(bit_and(bit_cast(x), 0x7fff'ffff)); }
|
||||
F32 fract(F32 x) { return sub(x, floor(x)); }
|
||||
F32 ceil(F32);
|
||||
F32 floor(F32);
|
||||
I32 is_NaN(F32 x) { return neq(x,x); }
|
||||
|
||||
@ -978,6 +980,7 @@ namespace skvm {
|
||||
|
||||
static inline F32 clamp01(F32 x) { return x->clamp01(x); }
|
||||
static inline F32 abs(F32 x) { return x-> abs(x); }
|
||||
static inline F32 ceil(F32 x) { return x-> ceil(x); }
|
||||
static inline F32 fract(F32 x) { return x-> fract(x); }
|
||||
static inline F32 floor(F32 x) { return x-> floor(x); }
|
||||
static inline I32 is_NaN(F32 x) { return x-> is_NaN(x); }
|
||||
|
@ -229,6 +229,7 @@ namespace SK_OPTS_NS {
|
||||
|
||||
CASE(Op::pack): r(d).u32 = r(x).u32 | (r(y).u32 << immz); break;
|
||||
|
||||
CASE(Op::ceil): r(d).f32 = skvx::ceil(r(x).f32) ; break;
|
||||
CASE(Op::floor): r(d).f32 = skvx::floor(r(x).f32) ; break;
|
||||
CASE(Op::to_f32): r(d).f32 = skvx::cast<float>( r(x).i32 ); break;
|
||||
CASE(Op::trunc): r(d).i32 = skvx::cast<int> ( r(x).f32 ); break;
|
||||
|
@ -61,6 +61,7 @@ static const uint8_t* DisassembleInstruction(const uint8_t* ip) {
|
||||
printf("callexternal %d, %d, %d", argumentCount, returnCount, externalValue);
|
||||
break;
|
||||
}
|
||||
VECTOR_DISASSEMBLE(kCeil, "ceil")
|
||||
case ByteCodeInstruction::kClampIndex: printf("clampindex %d", READ8()); break;
|
||||
VECTOR_DISASSEMBLE(kCompareIEQ, "compareieq")
|
||||
VECTOR_DISASSEMBLE(kCompareINEQ, "compareineq")
|
||||
@ -86,6 +87,7 @@ static const uint8_t* DisassembleInstruction(const uint8_t* ip) {
|
||||
VECTOR_DISASSEMBLE(kDivideS, "divideS")
|
||||
VECTOR_DISASSEMBLE(kDivideU, "divideu")
|
||||
VECTOR_MATRIX_DISASSEMBLE(kDup, "dup")
|
||||
VECTOR_DISASSEMBLE(kFloor, "floor")
|
||||
VECTOR_DISASSEMBLE(kFract, "fract")
|
||||
case ByteCodeInstruction::kInverse2x2: printf("inverse2x2"); break;
|
||||
case ByteCodeInstruction::kInverse3x3: printf("inverse3x3"); break;
|
||||
@ -553,6 +555,8 @@ static bool InnerRun(const ByteCode* byteCode, const ByteCodeFunction* f, VValue
|
||||
continue;
|
||||
}
|
||||
|
||||
VECTOR_UNARY_FN(kCeil, skvx::ceil, fFloat)
|
||||
|
||||
case ByteCodeInstruction::kClampIndex: {
|
||||
int length = READ8();
|
||||
if (skvx::any(mask() & ((sp[0].fSigned < 0) | (sp[0].fSigned >= length)))) {
|
||||
@ -643,6 +647,7 @@ static bool InnerRun(const ByteCode* byteCode, const ByteCodeFunction* f, VValue
|
||||
continue;
|
||||
}
|
||||
|
||||
VECTOR_UNARY_FN(kFloor, skvx::floor, fFloat)
|
||||
VECTOR_UNARY_FN(kFract, skvx::fract, fFloat)
|
||||
|
||||
case ByteCodeInstruction::kInverse2x2:
|
||||
|
@ -34,6 +34,7 @@ enum class ByteCodeInstruction : uint16_t {
|
||||
// Followed by three bytes indicating: the number of argument slots, the number of return slots,
|
||||
// and the index of the external value to call
|
||||
kCallExternal,
|
||||
VECTOR(kCeil),
|
||||
// For dynamic array access: Followed by byte indicating length of array
|
||||
kClampIndex,
|
||||
VECTOR(kCompareIEQ),
|
||||
@ -61,6 +62,7 @@ enum class ByteCodeInstruction : uint16_t {
|
||||
VECTOR(kDivideU),
|
||||
// Duplicates the top stack value
|
||||
VECTOR_MATRIX(kDup),
|
||||
VECTOR(kFloor),
|
||||
VECTOR(kFract),
|
||||
kInverse2x2,
|
||||
kInverse3x3,
|
||||
|
@ -47,9 +47,11 @@ ByteCodeGenerator::ByteCodeGenerator(const Context* context, const Program* prog
|
||||
// You can probably copy the declarations from sksl_gpu.inc.
|
||||
, fIntrinsics {
|
||||
{ "atan", ByteCodeInstruction::kATan },
|
||||
{ "ceil", ByteCodeInstruction::kCeil },
|
||||
{ "clamp", SpecialIntrinsic::kClamp },
|
||||
{ "cos", ByteCodeInstruction::kCos },
|
||||
{ "dot", SpecialIntrinsic::kDot },
|
||||
{ "floor", ByteCodeInstruction::kFloor },
|
||||
{ "fract", ByteCodeInstruction::kFract },
|
||||
{ "inverse", ByteCodeInstruction::kInverse2x2 },
|
||||
{ "length", SpecialIntrinsic::kLength },
|
||||
@ -257,7 +259,9 @@ int ByteCodeGenerator::StackUsage(ByteCodeInstruction inst, int count_) {
|
||||
VECTOR_UNARY_OP(kConvertUtoF)
|
||||
|
||||
VECTOR_UNARY_OP(kATan)
|
||||
VECTOR_UNARY_OP(kCeil)
|
||||
VECTOR_UNARY_OP(kCos)
|
||||
VECTOR_UNARY_OP(kFloor)
|
||||
VECTOR_UNARY_OP(kFract)
|
||||
VECTOR_UNARY_OP(kSin)
|
||||
VECTOR_UNARY_OP(kSqrt)
|
||||
|
Loading…
Reference in New Issue
Block a user