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:
parent
0ef780befd
commit
ba9da466cc
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user