radial gradients in skvm

- Add sqrt(), vsqrtps for x86.
- Hook into SkRadialGradient.

Change-Id: I66a4598e30fe16610c59a512f7d962323ee5134a
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/267196
Reviewed-by: Mike Reed <reed@google.com>
Commit-Queue: Mike Klein <mtklein@google.com>
This commit is contained in:
Mike Klein 2020-01-28 14:25:09 -06:00 committed by Skia Commit-Bot
parent 0ef780befd
commit ba9da466cc
9 changed files with 39 additions and 8 deletions

View File

@ -162,6 +162,8 @@ namespace skvm {
case Op::max_f32: write(o, V{id}, "=", op, V{x}, V{y} ); break;
case Op::mad_f32: write(o, V{id}, "=", op, V{x}, V{y}, V{z}); break;
case Op::sqrt_f32: write(o, V{id}, "=", op, V{x}); break;
case Op::add_f32_imm: write(o, V{id}, "=", op, V{x}, Splat{immy}); break;
case Op::sub_f32_imm: write(o, V{id}, "=", op, V{x}, Splat{immy}); break;
case Op::mul_f32_imm: write(o, V{id}, "=", op, V{x}, Splat{immy}); break;
@ -285,6 +287,8 @@ namespace skvm {
case Op::max_f32: write(o, R{d}, "=", op, R{x}, R{y} ); break;
case Op::mad_f32: write(o, R{d}, "=", op, R{x}, R{y}, R{z}); break;
case Op::sqrt_f32: write(o, R{d}, "=", op, R{x}); break;
case Op::add_f32_imm: write(o, R{d}, "=", op, R{x}, Splat{immy}); break;
case Op::sub_f32_imm: write(o, R{d}, "=", op, R{x}, Splat{immy}); break;
case Op::mul_f32_imm: write(o, R{d}, "=", op, R{x}, Splat{immy}); break;
@ -620,6 +624,12 @@ namespace skvm {
return {this->push(Op::mad_f32, x.id, y.id, z.id)};
}
F32 Builder::sqrt(F32 x) {
float X;
if (this->allImm(x.id,&X)) { return this->splat(std::sqrt(X)); }
return {this->push(Op::sqrt_f32, x.id,NA,NA)};
}
F32 Builder::min(F32 x, F32 y) {
float X,Y;
if (this->allImm(x.id,&X, y.id,&Y)) { return this->splat(std::min(X,Y)); }
@ -1111,9 +1121,10 @@ namespace skvm {
void Assembler::vmovdqa(Ymm dst, Ymm src) { this->op(0x66,0x0f,0x6f, dst,src); }
void Assembler::vcvtdq2ps (Ymm dst, Ymm x) { this->op(0, 0x0f,0x5b, dst,x); }
void Assembler::vcvtdq2ps (Ymm dst, Ymm x) { this->op( 0,0x0f,0x5b, dst,x); }
void Assembler::vcvttps2dq(Ymm dst, Ymm x) { this->op(0xf3,0x0f,0x5b, dst,x); }
void Assembler::vcvtps2dq (Ymm dst, Ymm x) { this->op(0x66,0x0f,0x5b, dst,x); }
void Assembler::vsqrtps (Ymm dst, Ymm x) { this->op( 0,0x0f,0x51, dst,x); }
Assembler::Label Assembler::here() {
return { (int)this->size(), Label::NotYetSet, {} };
@ -1777,6 +1788,8 @@ namespace skvm {
CASE(Op::mad_f32): r(d).f32 = r(x).f32 * r(y).f32 + r(z).f32; break;
CASE(Op::sqrt_f32): r(d).f32 = sqrt(r(x).f32); break;
CASE(Op::add_i32): r(d).i32 = r(x).i32 + r(y).i32; break;
CASE(Op::sub_i32): r(d).i32 = r(x).i32 - r(y).i32; break;
CASE(Op::mul_i32): r(d).i32 = r(x).i32 * r(y).i32; break;
@ -2349,6 +2362,7 @@ namespace skvm {
a->vmovdqa (dst(),r[x]);
a->vfmadd132ps(dst(),r[z], r[y]); }
break;
case Op::sqrt_f32: a->vsqrtps(dst(), r[x]); break;
case Op::add_f32_imm: a->vaddps(dst(), r[x], &constants[immy].label); break;
case Op::sub_f32_imm: a->vsubps(dst(), r[x], &constants[immy].label); break;

View File

@ -113,7 +113,7 @@ namespace skvm {
enum { NEAREST, FLOOR, CEIL, TRUNC }; // vroundps immediates
using DstEqOpX = void(Ymm dst, Ymm x);
DstEqOpX vmovdqa, vcvtdq2ps, vcvttps2dq, vcvtps2dq;
DstEqOpX vmovdqa, vcvtdq2ps, vcvttps2dq, vcvtps2dq, vsqrtps;
void vpblendvb(Ymm dst, Ymm x, Ymm y, Ymm z);
@ -296,6 +296,7 @@ namespace skvm {
M(min_f32) \
M(max_f32) \
M(mad_f32) \
M(sqrt_f32) \
M(shl_i32) M(shl_i16x2) \
M(shr_i32) M(shr_i16x2) \
M(sra_i32) M(sra_i16x2) \
@ -424,6 +425,7 @@ namespace skvm {
F32 min(F32 x, F32 y);
F32 max(F32 x, F32 y);
F32 mad(F32 x, F32 y, F32 z); // x*y+z, often an FMA
F32 sqrt(F32 x);
F32 lerp(F32 lo, F32 hi, F32 t) {
return mad(sub(hi,lo), t, lo);

View File

@ -430,10 +430,9 @@ bool SkGradientShaderBase::onProgram(skvm::Builder* p,
inv.postConcat(fPtsToUnit);
inv.normalizePerspective();
// Having tacked on fPtsToUnit at the end means we'll be left with t in x.
SkShaderBase::ApplyMatrix(p, inv, &x,&y,uniforms);
skvm::F32 t = x;
if (!this->transformT(p, &t)) { // Hook into subclasses for linear, radial, etc.
skvm::F32 t;
if (!this->transformT(p, x,y, &t)) { // Hook into subclasses for linear, radial, etc.
return false;
}

View File

@ -14,6 +14,7 @@
#include "include/private/SkTArray.h"
#include "include/private/SkTemplates.h"
#include "src/core/SkArenaAlloc.h"
#include "src/core/SkVM.h"
#include "src/shaders/SkShaderBase.h"
class SkColorSpace;
@ -88,7 +89,9 @@ protected:
virtual void appendGradientStages(SkArenaAlloc* alloc, SkRasterPipeline* tPipeline,
SkRasterPipeline* postPipeline) const = 0;
virtual bool transformT(skvm::Builder*, skvm::F32* t) const { return false; }
virtual bool transformT(skvm::Builder*, skvm::F32 x, skvm::F32 y, skvm::F32* t) const {
return false;
}
template <typename T, typename... Args>
static Context* CheckedMakeContext(SkArenaAlloc* alloc, Args&&... args) {

View File

@ -75,7 +75,11 @@ void SkLinearGradient::appendGradientStages(SkArenaAlloc*, SkRasterPipeline*,
// No extra stage needed for linear gradients.
}
bool SkLinearGradient::transformT(skvm::Builder*, skvm::F32*) const { return true; }
bool SkLinearGradient::transformT(skvm::Builder* p, skvm::F32 x, skvm::F32 y, skvm::F32* t) const {
// We've baked getting t in x into the matrix, so this is pretty trivial.
*t = x;
return true;
}
SkShader::GradientType SkLinearGradient::asAGradient(GradientInfo* info) const {
if (info) {

View File

@ -29,7 +29,7 @@ protected:
void appendGradientStages(SkArenaAlloc* alloc, SkRasterPipeline* tPipeline,
SkRasterPipeline* postPipeline) const final;
bool transformT(skvm::Builder*, skvm::F32* t) const final;
bool transformT(skvm::Builder*, skvm::F32 x, skvm::F32 y, skvm::F32* t) const final;
private:

View File

@ -63,6 +63,11 @@ void SkRadialGradient::appendGradientStages(SkArenaAlloc*, SkRasterPipeline* p,
p->append(SkRasterPipeline::xy_to_radius);
}
bool SkRadialGradient::transformT(skvm::Builder* p, skvm::F32 x, skvm::F32 y, skvm::F32* t) const {
*t = p->sqrt(p->mad(x,x, p->mul(y,y)));
return true;
}
/////////////////////////////////////////////////////////////////////
#if SK_SUPPORT_GPU

View File

@ -26,6 +26,8 @@ protected:
void appendGradientStages(SkArenaAlloc* alloc, SkRasterPipeline* tPipeline,
SkRasterPipeline* postPipeline) const override;
bool transformT(skvm::Builder*, skvm::F32 x, skvm::F32 y, skvm::F32* t) const final;
private:
SK_FLATTENABLE_HOOKS(SkRadialGradient)

View File

@ -1168,11 +1168,13 @@ DEF_TEST(SkVM_Assembler, r) {
a.vcvttps2dq(A::ymm3, A::ymm2);
a.vcvtdq2ps (A::ymm3, A::ymm2);
a.vcvtps2dq (A::ymm3, A::ymm2);
a.vsqrtps (A::ymm3, A::ymm2);
},{
0xc5,0xfd,0x6f,0xda,
0xc5,0xfe,0x5b,0xda,
0xc5,0xfc,0x5b,0xda,
0xc5,0xfd,0x5b,0xda,
0xc5,0xfc,0x51,0xda,
});
test_asm(r, [&](A& a) {