Supply device and local coords to SkShader_Base::onProgram
Use that to add support for sk_FragCoord in SkRuntimeEffect.
Change-Id: I587ad97057c13ec8a4052c7c20f655eae88786ba
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/298504
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Mike Klein <mtklein@google.com>
diff --git a/src/core/SkRuntimeEffect.cpp b/src/core/SkRuntimeEffect.cpp
index acab69c..6934dcd 100644
--- a/src/core/SkRuntimeEffect.cpp
+++ b/src/core/SkRuntimeEffect.cpp
@@ -415,7 +415,7 @@
std::vector<skvm::F32> stack,
/*these parameters are used to call program() on children*/
const std::vector<sk_sp<SkShader>>& children,
- skvm::F32 x, skvm::F32 y, skvm::Color paint,
+ skvm::Coord device, skvm::Color paint,
SkFilterQuality quality, const SkColorInfo& dst,
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) {
auto push = [&](skvm::F32 x) { stack.push_back(x); };
@@ -483,7 +483,7 @@
x = pop();
SkOverrideDeviceMatrixProvider mats{matrices, SkMatrix::I()};
- skvm::Color c = as_SB(children[ix])->program(p, x,y,paint,
+ skvm::Color c = as_SB(children[ix])->program(p, device, {x,y},paint,
mats, nullptr,
quality, dst,
uniforms, alloc);
@@ -548,6 +548,14 @@
push(uniform[ix + 3]);
} break;
+ case Inst::kLoadFragCoord: {
+ // TODO: Actually supply Z and 1/W from the rasterizer?
+ push(device.x);
+ push(device.y);
+ push(p->splat(0.0f)); // Z
+ push(p->splat(1.0f)); // 1/W
+ } break;
+
case Inst::kStore: {
int ix = u8();
stack[ix + 0] = pop();
@@ -828,7 +836,7 @@
std::vector<skvm::F32> stack =
program_fn(p, *fn, uniform, SkSimpleMatrixProvider{SkMatrix::I()}, {c.r, c.g, c.b, c.a},
/* the remaining parameters are for shaders only and won't be used here */
- {},{},{},{},{},{},{},{});
+ {},{},{},{},{},{},{});
if (stack.size() == 4) {
return {stack[0], stack[1], stack[2], stack[3]};
@@ -1017,7 +1025,8 @@
return true;
}
- skvm::Color onProgram(skvm::Builder* p, skvm::F32 x, skvm::F32 y, skvm::Color paint,
+ skvm::Color onProgram(skvm::Builder* p,
+ skvm::Coord device, skvm::Coord local, skvm::Color paint,
const SkMatrixProvider& matrices, const SkMatrix* localM,
SkFilterQuality quality, const SkColorInfo& dst,
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const override {
@@ -1047,12 +1056,13 @@
if (!this->computeTotalInverse(matrices.localToDevice(), localM, &inv)) {
return {};
}
- SkShaderBase::ApplyMatrix(p,inv, &x,&y,uniforms);
+ SkShaderBase::ApplyMatrix(p,inv, &local,uniforms);
std::vector<skvm::F32> stack =
- program_fn(p, *fn, uniform, matrices, {x,y, paint.r, paint.g, paint.b, paint.a},
+ program_fn(p, *fn, uniform, matrices,
+ {local.x,local.y, paint.r, paint.g, paint.b, paint.a},
/*parameters for calling program() on children*/
- fChildren, x,y,paint, quality,dst, uniforms,alloc);
+ fChildren, device,paint, quality,dst, uniforms,alloc);
if (stack.size() == 6) {
return {stack[2], stack[3], stack[4], stack[5]};
diff --git a/src/core/SkVM.h b/src/core/SkVM.h
index 609c01e..db5b273 100644
--- a/src/core/SkVM.h
+++ b/src/core/SkVM.h
@@ -476,6 +476,12 @@
Builder* operator->() const { return a.operator->(); }
};
+ struct Coord {
+ F32 x,y;
+ explicit operator bool() const { return x && y; }
+ Builder* operator->() const { return x.operator->(); }
+ };
+
struct Uniform {
Arg ptr;
int offset;
diff --git a/src/core/SkVMBlitter.cpp b/src/core/SkVMBlitter.cpp
index 8a8d42e..5469c4b 100644
--- a/src/core/SkVMBlitter.cpp
+++ b/src/core/SkVMBlitter.cpp
@@ -117,8 +117,9 @@
skvm::I32 dx = p.uniform32(uniforms->base, offsetof(BlitterUniforms, right))
- p.index(),
dy = p.uniform32(uniforms->base, offsetof(BlitterUniforms, y));
- skvm::F32 x = to_f32(dx) + 0.5f,
- y = to_f32(dy) + 0.5f;
+ skvm::Coord device = {to_f32(dx) + 0.5f,
+ to_f32(dy) + 0.5f},
+ local = device;
skvm::Color paint = {
p.uniformF(uniforms->base, offsetof(BlitterUniforms, paint.fR)),
@@ -129,7 +130,7 @@
uint64_t hash = 0;
if (auto c = sb->program(&p,
- x,y, paint,
+ device,local, paint,
params.matrices, /*localM=*/nullptr,
params.quality, params.dst,
uniforms,alloc)) {
@@ -197,8 +198,9 @@
skvm::I32 dx = p->uniform32(uniforms->base, offsetof(BlitterUniforms, right))
- p->index(),
dy = p->uniform32(uniforms->base, offsetof(BlitterUniforms, y));
- skvm::F32 x = to_f32(dx) + 0.5f,
- y = to_f32(dy) + 0.5f;
+ skvm::Coord device = {to_f32(dx) + 0.5f,
+ to_f32(dy) + 0.5f},
+ local = device;
skvm::Color paint = {
p->uniformF(uniforms->base, offsetof(BlitterUniforms, paint.fR)),
@@ -207,7 +209,7 @@
p->uniformF(uniforms->base, offsetof(BlitterUniforms, paint.fA)),
};
- skvm::Color src = as_SB(params.shader)->program(p, x,y, paint,
+ skvm::Color src = as_SB(params.shader)->program(p, device,local, paint,
params.matrices, /*localM=*/nullptr,
params.quality, params.dst,
uniforms, alloc);
@@ -274,7 +276,7 @@
}
if (params.clip) {
- skvm::Color clip = as_SB(params.clip)->program(p, x,y, paint,
+ skvm::Color clip = as_SB(params.clip)->program(p, device,local, paint,
params.matrices, /*localM=*/nullptr,
params.quality, params.dst,
uniforms, alloc);
@@ -428,12 +430,13 @@
bool isOpaque() const override { return fShader->isOpaque(); }
- skvm::Color onProgram(skvm::Builder* p, skvm::F32 x, skvm::F32 y, skvm::Color paint,
+ skvm::Color onProgram(skvm::Builder* p,
+ skvm::Coord device, skvm::Coord local, skvm::Color paint,
const SkMatrixProvider& matrices, const SkMatrix* localM,
SkFilterQuality quality, const SkColorInfo& dst,
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const override {
// Run our wrapped shader.
- skvm::Color c = as_SB(fShader)->program(p, x,y, paint,
+ skvm::Color c = as_SB(fShader)->program(p, device,local, paint,
matrices,localM, quality,dst, uniforms,alloc);
if (!c) {
return {};
@@ -467,8 +470,10 @@
// See SkRasterPipeline dither stage.
// This is 8x8 ordered dithering. From here we'll only need dx and dx^dy.
- skvm::I32 X = trunc(x - 0.5f),
- Y = X ^ trunc(y - 0.5f);
+ SkASSERT(local.x.id == device.x.id);
+ SkASSERT(local.y.id == device.y.id);
+ skvm::I32 X = trunc(device.x - 0.5f),
+ Y = X ^ trunc(device.y - 0.5f);
// If X's low bits are abc and Y's def, M is fcebda,
// 6 bits producing all values [0,63] shuffled over an 8x8 grid.
diff --git a/src/core/SkVM_fwd.h b/src/core/SkVM_fwd.h
index 1442a9f..e8dc43f 100644
--- a/src/core/SkVM_fwd.h
+++ b/src/core/SkVM_fwd.h
@@ -16,6 +16,7 @@
struct I32;
struct F32;
struct Color;
+ struct Coord;
struct Uniforms;
}
diff --git a/src/shaders/SkColorFilterShader.cpp b/src/shaders/SkColorFilterShader.cpp
index eb8b4e8..15b9a16 100644
--- a/src/shaders/SkColorFilterShader.cpp
+++ b/src/shaders/SkColorFilterShader.cpp
@@ -62,12 +62,12 @@
}
skvm::Color SkColorFilterShader::onProgram(skvm::Builder* p,
- skvm::F32 x, skvm::F32 y, skvm::Color paint,
+ skvm::Coord device, skvm::Coord local, skvm::Color paint,
const SkMatrixProvider& matrices, const SkMatrix* localM,
SkFilterQuality quality, const SkColorInfo& dst,
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const {
// Run the shader.
- skvm::Color c = as_SB(fShader)->program(p, x,y, paint,
+ skvm::Color c = as_SB(fShader)->program(p, device,local, paint,
matrices,localM,
quality,dst,
uniforms,alloc);
diff --git a/src/shaders/SkColorFilterShader.h b/src/shaders/SkColorFilterShader.h
index 348e437..e20af83 100644
--- a/src/shaders/SkColorFilterShader.h
+++ b/src/shaders/SkColorFilterShader.h
@@ -26,7 +26,7 @@
void flatten(SkWriteBuffer&) const override;
bool onAppendStages(const SkStageRec&) const override;
- skvm::Color onProgram(skvm::Builder*, skvm::F32 x, skvm::F32 y, skvm::Color paint,
+ skvm::Color onProgram(skvm::Builder*, skvm::Coord device, skvm::Coord local, skvm::Color paint,
const SkMatrixProvider&, const SkMatrix* localM,
SkFilterQuality quality, const SkColorInfo& dst,
skvm::Uniforms* uniforms, SkArenaAlloc*) const override;
diff --git a/src/shaders/SkColorShader.cpp b/src/shaders/SkColorShader.cpp
index 7fbd6ad..8afdda1 100644
--- a/src/shaders/SkColorShader.cpp
+++ b/src/shaders/SkColorShader.cpp
@@ -92,7 +92,8 @@
}
skvm::Color SkColorShader::onProgram(skvm::Builder* p,
- skvm::F32 /*x*/, skvm::F32 /*y*/, skvm::Color /*paint*/,
+ skvm::Coord /*device*/, skvm::Coord /*local*/,
+ skvm::Color /*paint*/,
const SkMatrixProvider&, const SkMatrix* /*localM*/,
SkFilterQuality /*quality*/, const SkColorInfo& dst,
skvm::Uniforms* uniforms, SkArenaAlloc*) const {
@@ -100,7 +101,8 @@
uniforms, dst.colorSpace());
}
skvm::Color SkColor4Shader::onProgram(skvm::Builder* p,
- skvm::F32 /*x*/, skvm::F32 /*y*/, skvm::Color /*paint*/,
+ skvm::Coord /*device*/, skvm::Coord /*local*/,
+ skvm::Color /*paint*/,
const SkMatrixProvider&, const SkMatrix* /*localM*/,
SkFilterQuality /*quality*/, const SkColorInfo& dst,
skvm::Uniforms* uniforms, SkArenaAlloc*) const {
diff --git a/src/shaders/SkColorShader.h b/src/shaders/SkColorShader.h
index ecf305e..5b87665 100644
--- a/src/shaders/SkColorShader.h
+++ b/src/shaders/SkColorShader.h
@@ -44,7 +44,7 @@
bool onAppendStages(const SkStageRec&) const override;
- skvm::Color onProgram(skvm::Builder*, skvm::F32 x, skvm::F32 y, skvm::Color paint,
+ skvm::Color onProgram(skvm::Builder*, skvm::Coord device, skvm::Coord local, skvm::Color paint,
const SkMatrixProvider&, const SkMatrix* localM,
SkFilterQuality quality, const SkColorInfo& dst,
skvm::Uniforms* uniforms, SkArenaAlloc*) const override;
@@ -69,7 +69,7 @@
void flatten(SkWriteBuffer&) const override;
bool onAppendStages(const SkStageRec&) const override;
- skvm::Color onProgram(skvm::Builder*, skvm::F32 x, skvm::F32 y, skvm::Color paint,
+ skvm::Color onProgram(skvm::Builder*, skvm::Coord device, skvm::Coord local, skvm::Color paint,
const SkMatrixProvider&, const SkMatrix* localM,
SkFilterQuality quality, const SkColorInfo& dst,
skvm::Uniforms* uniforms, SkArenaAlloc*) const override;
diff --git a/src/shaders/SkComposeShader.cpp b/src/shaders/SkComposeShader.cpp
index 9c508f0..77fbfeb 100644
--- a/src/shaders/SkComposeShader.cpp
+++ b/src/shaders/SkComposeShader.cpp
@@ -127,13 +127,14 @@
return true;
}
-skvm::Color SkShader_Blend::onProgram(skvm::Builder* p, skvm::F32 x, skvm::F32 y, skvm::Color paint,
- const SkMatrixProvider& matrices, const SkMatrix* localM,
+skvm::Color SkShader_Blend::onProgram(skvm::Builder* p,
+ skvm::Coord device, skvm::Coord local, skvm::Color paint,
+ const SkMatrixProvider& mats, const SkMatrix* localM,
SkFilterQuality q, const SkColorInfo& dst,
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const {
skvm::Color d,s;
- if ((d = as_SB(fDst)->program(p, x,y, paint, matrices,localM, q, dst, uniforms, alloc)) &&
- (s = as_SB(fSrc)->program(p, x,y, paint, matrices,localM, q, dst, uniforms, alloc)))
+ if ((d = as_SB(fDst)->program(p, device,local, paint, mats,localM, q,dst, uniforms,alloc)) &&
+ (s = as_SB(fSrc)->program(p, device,local, paint, mats,localM, q,dst, uniforms,alloc)))
{
return p->blend(fMode, s,d);
}
@@ -167,13 +168,14 @@
return true;
}
-skvm::Color SkShader_Lerp::onProgram(skvm::Builder* p, skvm::F32 x, skvm::F32 y, skvm::Color paint,
- const SkMatrixProvider& matrices, const SkMatrix* localM,
+skvm::Color SkShader_Lerp::onProgram(skvm::Builder* p,
+ skvm::Coord device, skvm::Coord local, skvm::Color paint,
+ const SkMatrixProvider& mats, const SkMatrix* localM,
SkFilterQuality q, const SkColorInfo& dst,
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const {
skvm::Color d,s;
- if ((d = as_SB(fDst)->program(p, x,y, paint, matrices,localM, q, dst, uniforms, alloc)) &&
- (s = as_SB(fSrc)->program(p, x,y, paint, matrices,localM, q, dst, uniforms, alloc)))
+ if ((d = as_SB(fDst)->program(p, device,local, paint, mats,localM, q,dst, uniforms,alloc)) &&
+ (s = as_SB(fSrc)->program(p, device,local, paint, mats,localM, q,dst, uniforms,alloc)))
{
auto t = p->uniformF(uniforms->pushF(fWeight));
return {
diff --git a/src/shaders/SkComposeShader.h b/src/shaders/SkComposeShader.h
index b19c4c4..96ae0a0 100644
--- a/src/shaders/SkComposeShader.h
+++ b/src/shaders/SkComposeShader.h
@@ -27,7 +27,7 @@
SkShader_Blend(SkReadBuffer&);
void flatten(SkWriteBuffer&) const override;
bool onAppendStages(const SkStageRec&) const override;
- skvm::Color onProgram(skvm::Builder*, skvm::F32 x, skvm::F32 y, skvm::Color paint,
+ skvm::Color onProgram(skvm::Builder*, skvm::Coord device, skvm::Coord local, skvm::Color paint,
const SkMatrixProvider&, const SkMatrix* localM,
SkFilterQuality, const SkColorInfo& dst,
skvm::Uniforms*, SkArenaAlloc*) const override;
@@ -60,7 +60,7 @@
SkShader_Lerp(SkReadBuffer&);
void flatten(SkWriteBuffer&) const override;
bool onAppendStages(const SkStageRec&) const override;
- skvm::Color onProgram(skvm::Builder*, skvm::F32 x, skvm::F32 y, skvm::Color paint,
+ skvm::Color onProgram(skvm::Builder*, skvm::Coord device, skvm::Coord local, skvm::Color paint,
const SkMatrixProvider&, const SkMatrix* localM,
SkFilterQuality, const SkColorInfo& dst,
skvm::Uniforms*, SkArenaAlloc*) const override;
diff --git a/src/shaders/SkEmptyShader.h b/src/shaders/SkEmptyShader.h
index d5d7950..414be6c 100644
--- a/src/shaders/SkEmptyShader.h
+++ b/src/shaders/SkEmptyShader.h
@@ -37,7 +37,7 @@
return false;
}
- skvm::Color onProgram(skvm::Builder*, skvm::F32, skvm::F32, skvm::Color,
+ skvm::Color onProgram(skvm::Builder*, skvm::Coord, skvm::Coord, skvm::Color,
const SkMatrixProvider&, const SkMatrix*,
SkFilterQuality, const SkColorInfo&,
skvm::Uniforms*, SkArenaAlloc*) const override;
diff --git a/src/shaders/SkImageShader.cpp b/src/shaders/SkImageShader.cpp
index 82edbc5..bc1b36a 100755
--- a/src/shaders/SkImageShader.cpp
+++ b/src/shaders/SkImageShader.cpp
@@ -639,7 +639,8 @@
return this->doStages(rec, updater) ? updater : nullptr;
}
-skvm::Color SkImageShader::onProgram(skvm::Builder* p, skvm::F32 x, skvm::F32 y, skvm::Color paint,
+skvm::Color SkImageShader::onProgram(skvm::Builder* p,
+ skvm::Coord device, skvm::Coord local, skvm::Color paint,
const SkMatrixProvider& matrices, const SkMatrix* localM,
SkFilterQuality quality, const SkColorInfo& dst,
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const {
@@ -663,7 +664,7 @@
inv.normalizePerspective();
// Apply matrix to convert dst coords to sample center coords.
- SkShaderBase::ApplyMatrix(p, inv, &x,&y,uniforms);
+ SkShaderBase::ApplyMatrix(p, inv, &local, uniforms);
// Bail out if sample() can't yet handle our image's color type.
switch (pm.colorType()) {
@@ -788,14 +789,14 @@
skvm::Color c;
if (quality == kNone_SkFilterQuality) {
- c = sample(x,y);
+ c = sample(local.x,local.y);
} else if (quality == kLow_SkFilterQuality) {
// Our four sample points are the corners of a logical 1x1 pixel
// box surrounding (x,y) at (0.5,0.5) off-center.
- skvm::F32 left = x - 0.5f,
- top = y - 0.5f,
- right = x + 0.5f,
- bottom = y + 0.5f;
+ skvm::F32 left = local.x - 0.5f,
+ top = local.y - 0.5f,
+ right = local.x + 0.5f,
+ bottom = local.y + 0.5f;
// The fractional parts of right and bottom are our lerp factors in x and y respectively.
skvm::F32 fx = fract(right ),
@@ -808,8 +809,8 @@
// All bicubic samples have the same fractional offset (fx,fy) from the center.
// They're either the 16 corners of a 3x3 grid/ surrounding (x,y) at (0.5,0.5) off-center.
- skvm::F32 fx = fract(x + 0.5f),
- fy = fract(y + 0.5f);
+ skvm::F32 fx = fract(local.x + 0.5f),
+ fy = fract(local.y + 0.5f);
// See GrCubicEffect for details of these weights.
// TODO: these maybe don't seem right looking at gm/bicubic and GrBicubicEffect.
@@ -836,9 +837,9 @@
c.r = c.g = c.b = c.a = p->splat(0.0f);
- skvm::F32 sy = y - 1.5f;
+ skvm::F32 sy = local.y - 1.5f;
for (int j = 0; j < 4; j++, sy += 1.0f) {
- skvm::F32 sx = x - 1.5f;
+ skvm::F32 sx = local.x - 1.5f;
for (int i = 0; i < 4; i++, sx += 1.0f) {
skvm::Color s = sample(sx,sy);
skvm::F32 w = wx[i] * wy[j];
diff --git a/src/shaders/SkImageShader.h b/src/shaders/SkImageShader.h
index 3a6f197..a653a9f 100644
--- a/src/shaders/SkImageShader.h
+++ b/src/shaders/SkImageShader.h
@@ -58,7 +58,7 @@
bool onAppendStages(const SkStageRec&) const override;
SkStageUpdater* onAppendUpdatableStages(const SkStageRec&) const override;
- skvm::Color onProgram(skvm::Builder*, skvm::F32 x, skvm::F32 y, skvm::Color paint,
+ skvm::Color onProgram(skvm::Builder*, skvm::Coord device, skvm::Coord local, skvm::Color paint,
const SkMatrixProvider&, const SkMatrix* localM,
SkFilterQuality quality, const SkColorInfo& dst,
skvm::Uniforms* uniforms, SkArenaAlloc*) const override;
diff --git a/src/shaders/SkLocalMatrixShader.cpp b/src/shaders/SkLocalMatrixShader.cpp
index 1caa035..c0ef126 100644
--- a/src/shaders/SkLocalMatrixShader.cpp
+++ b/src/shaders/SkLocalMatrixShader.cpp
@@ -78,7 +78,7 @@
skvm::Color SkLocalMatrixShader::onProgram(skvm::Builder* p,
- skvm::F32 x, skvm::F32 y, skvm::Color paint,
+ skvm::Coord device, skvm::Coord local, skvm::Color paint,
const SkMatrixProvider& matrices, const SkMatrix* localM,
SkFilterQuality quality, const SkColorInfo& dst,
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const {
@@ -86,7 +86,7 @@
if (localM) {
lm.writable()->preConcat(*localM);
}
- return as_SB(fProxyShader)->program(p, x,y, paint,
+ return as_SB(fProxyShader)->program(p, device,local, paint,
matrices,lm.get(),
quality,dst,
uniforms,alloc);
@@ -156,12 +156,13 @@
return as_SB(fProxyShader)->appendStages(newRec);
}
- skvm::Color onProgram(skvm::Builder* p, skvm::F32 x, skvm::F32 y, skvm::Color paint,
+ skvm::Color onProgram(skvm::Builder* p,
+ skvm::Coord device, skvm::Coord local, skvm::Color paint,
const SkMatrixProvider& matrices, const SkMatrix* localM,
SkFilterQuality quality, const SkColorInfo& dst,
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const override {
SkOverrideDeviceMatrixProvider matrixProvider(matrices, fCTM);
- return as_SB(fProxyShader)->program(p, x,y,paint,
+ return as_SB(fProxyShader)->program(p, device,local, paint,
matrixProvider,localM,
quality,dst,
uniforms,alloc);
diff --git a/src/shaders/SkLocalMatrixShader.h b/src/shaders/SkLocalMatrixShader.h
index 845b0f4..b1fd882 100644
--- a/src/shaders/SkLocalMatrixShader.h
+++ b/src/shaders/SkLocalMatrixShader.h
@@ -48,7 +48,7 @@
bool onAppendStages(const SkStageRec&) const override;
- skvm::Color onProgram(skvm::Builder*, skvm::F32 x, skvm::F32 y, skvm::Color paint,
+ skvm::Color onProgram(skvm::Builder*, skvm::Coord device, skvm::Coord local, skvm::Color paint,
const SkMatrixProvider&, const SkMatrix* localM,
SkFilterQuality quality, const SkColorInfo& dst,
skvm::Uniforms* uniforms, SkArenaAlloc*) const override;
diff --git a/src/shaders/SkPictureShader.cpp b/src/shaders/SkPictureShader.cpp
index ab5db0b..6a77004 100644
--- a/src/shaders/SkPictureShader.cpp
+++ b/src/shaders/SkPictureShader.cpp
@@ -275,7 +275,7 @@
}
skvm::Color SkPictureShader::onProgram(skvm::Builder* p,
- skvm::F32 x, skvm::F32 y, skvm::Color paint,
+ skvm::Coord device, skvm::Coord local, skvm::Color paint,
const SkMatrixProvider& matrices, const SkMatrix* localM,
SkFilterQuality quality, const SkColorInfo& dst,
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const {
@@ -289,7 +289,10 @@
return {};
}
- return as_SB(bitmapShader)->program(p, x,y, paint, matrices, lm, quality, dst, uniforms, alloc);
+ return as_SB(bitmapShader)->program(p, device,local, paint,
+ matrices,lm,
+ quality,dst,
+ uniforms,alloc);
}
/////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/shaders/SkPictureShader.h b/src/shaders/SkPictureShader.h
index 98eb761..01ef4b4 100644
--- a/src/shaders/SkPictureShader.h
+++ b/src/shaders/SkPictureShader.h
@@ -37,7 +37,7 @@
SkPictureShader(SkReadBuffer&);
void flatten(SkWriteBuffer&) const override;
bool onAppendStages(const SkStageRec&) const override;
- skvm::Color onProgram(skvm::Builder*, skvm::F32 x, skvm::F32 y, skvm::Color paint,
+ skvm::Color onProgram(skvm::Builder*, skvm::Coord device, skvm::Coord local, skvm::Color paint,
const SkMatrixProvider&, const SkMatrix* localM,
SkFilterQuality quality, const SkColorInfo& dst,
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const override;
diff --git a/src/shaders/SkShader.cpp b/src/shaders/SkShader.cpp
index 0514e8c..573fe50 100644
--- a/src/shaders/SkShader.cpp
+++ b/src/shaders/SkShader.cpp
@@ -195,7 +195,8 @@
return false;
}
-skvm::Color SkShaderBase::program(skvm::Builder* p, skvm::F32 x, skvm::F32 y, skvm::Color paint,
+skvm::Color SkShaderBase::program(skvm::Builder* p,
+ skvm::Coord device, skvm::Coord local, skvm::Color paint,
const SkMatrixProvider& matrices, const SkMatrix* localM,
SkFilterQuality quality, const SkColorInfo& dst,
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const {
@@ -211,7 +212,8 @@
// shader program hash and blitter Key. This makes it safe for us to use
// that bit to make decisions when constructing an SkVMBlitter, like doing
// SrcOver -> Src strength reduction.
- if (auto color = this->onProgram(p, x,y, paint, matrices,localM, quality,dst, uniforms,alloc)) {
+ if (auto color = this->onProgram(p, device,local, paint, matrices,localM, quality,dst,
+ uniforms,alloc)) {
if (this->isOpaque()) {
color.a = p->splat(1.0f);
}
@@ -220,11 +222,12 @@
return {};
}
-skvm::Color SkShaderBase::onProgram(skvm::Builder*, skvm::F32 x, skvm::F32 y, skvm::Color paint,
+skvm::Color SkShaderBase::onProgram(skvm::Builder*,
+ skvm::Coord device, skvm::Coord local, skvm::Color paint,
const SkMatrixProvider&, const SkMatrix* localM,
SkFilterQuality quality, const SkColorInfo& dst,
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const {
- //SkDebugf("cannot onProgram %s\n", this->getTypeName());
+ // SkDebugf("cannot onProgram %s\n", this->getTypeName());
return {};
}
@@ -235,7 +238,9 @@
void SkShaderBase::ApplyMatrix(skvm::Builder* p, const SkMatrix& m,
- skvm::F32* x, skvm::F32* y, skvm::Uniforms* uniforms) {
+ skvm::Coord* coord, skvm::Uniforms* uniforms) {
+ skvm::F32 *x = &coord->x,
+ *y = &coord->y;
if (m.isIdentity()) {
// That was easy.
} else if (m.isTranslate()) {
@@ -261,7 +266,7 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
-skvm::Color SkEmptyShader::onProgram(skvm::Builder*, skvm::F32, skvm::F32, skvm::Color,
+skvm::Color SkEmptyShader::onProgram(skvm::Builder*, skvm::Coord, skvm::Coord, skvm::Color,
const SkMatrixProvider&, const SkMatrix*,
SkFilterQuality, const SkColorInfo&,
skvm::Uniforms*, SkArenaAlloc*) const {
diff --git a/src/shaders/SkShaderBase.h b/src/shaders/SkShaderBase.h
index 7ef46dd..e9283cd 100644
--- a/src/shaders/SkShaderBase.h
+++ b/src/shaders/SkShaderBase.h
@@ -211,7 +211,7 @@
return this->onAppendUpdatableStages(rec);
}
- skvm::Color program(skvm::Builder*, skvm::F32 x, skvm::F32 y, skvm::Color paint,
+ skvm::Color program(skvm::Builder*, skvm::Coord device, skvm::Coord local, skvm::Color paint,
const SkMatrixProvider&, const SkMatrix* localM,
SkFilterQuality quality, const SkColorInfo& dst,
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const;
@@ -241,13 +241,14 @@
virtual SkStageUpdater* onAppendUpdatableStages(const SkStageRec&) const { return nullptr; }
protected:
- static void ApplyMatrix(skvm::Builder*, const SkMatrix&, skvm::F32* x, skvm::F32* y, skvm::Uniforms*);
+ static void ApplyMatrix(skvm::Builder*, const SkMatrix&, skvm::Coord*, skvm::Uniforms*);
private:
// This is essentially const, but not officially so it can be modified in constructors.
SkMatrix fLocalMatrix;
- virtual skvm::Color onProgram(skvm::Builder*, skvm::F32 x, skvm::F32 y, skvm::Color paint,
+ virtual skvm::Color onProgram(skvm::Builder*,
+ skvm::Coord device, skvm::Coord local, skvm::Color paint,
const SkMatrixProvider&, const SkMatrix* localM,
SkFilterQuality quality, const SkColorInfo& dst,
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const;
diff --git a/src/shaders/gradients/SkGradientShader.cpp b/src/shaders/gradients/SkGradientShader.cpp
index 61e9b3a..6a495b5 100644
--- a/src/shaders/gradients/SkGradientShader.cpp
+++ b/src/shaders/gradients/SkGradientShader.cpp
@@ -420,7 +420,8 @@
}
skvm::Color SkGradientShaderBase::onProgram(skvm::Builder* p,
- skvm::F32 x, skvm::F32 y, skvm::Color /*paint*/,
+ skvm::Coord device, skvm::Coord local,
+ skvm::Color /*paint*/,
const SkMatrixProvider& mats, const SkMatrix* localM,
SkFilterQuality quality, const SkColorInfo& dstInfo,
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const {
@@ -431,10 +432,10 @@
inv.postConcat(fPtsToUnit);
inv.normalizePerspective();
- SkShaderBase::ApplyMatrix(p, inv, &x,&y,uniforms);
+ SkShaderBase::ApplyMatrix(p, inv, &local, uniforms);
skvm::I32 mask = p->splat(~0);
- skvm::F32 t = this->transformT(p,uniforms, x,y, &mask);
+ skvm::F32 t = this->transformT(p,uniforms, local, &mask);
// Perhaps unexpectedly, clamping is handled naturally by our search, so we
// don't explicitly clamp t to [0,1]. That clamp would break hard stops
diff --git a/src/shaders/gradients/SkGradientShaderPriv.h b/src/shaders/gradients/SkGradientShaderPriv.h
index b38b1e8..f33c444 100644
--- a/src/shaders/gradients/SkGradientShaderPriv.h
+++ b/src/shaders/gradients/SkGradientShaderPriv.h
@@ -79,7 +79,7 @@
bool onAppendStages(const SkStageRec&) const override;
- skvm::Color onProgram(skvm::Builder* p, skvm::F32 x, skvm::F32 y, skvm::Color paint,
+ skvm::Color onProgram(skvm::Builder*, skvm::Coord device, skvm::Coord local, skvm::Color paint,
const SkMatrixProvider&, const SkMatrix* localM,
SkFilterQuality quality, const SkColorInfo& dstCS,
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const override;
@@ -89,7 +89,7 @@
// Produce t from (x,y), modifying mask if it should be anything other than ~0.
virtual skvm::F32 transformT(skvm::Builder*, skvm::Uniforms*,
- skvm::F32 x, skvm::F32 y, skvm::I32* mask) const = 0;
+ skvm::Coord coord, skvm::I32* mask) const = 0;
template <typename T, typename... Args>
static Context* CheckedMakeContext(SkArenaAlloc* alloc, Args&&... args) {
diff --git a/src/shaders/gradients/SkLinearGradient.cpp b/src/shaders/gradients/SkLinearGradient.cpp
index ad5129c..347fd17 100644
--- a/src/shaders/gradients/SkLinearGradient.cpp
+++ b/src/shaders/gradients/SkLinearGradient.cpp
@@ -76,9 +76,9 @@
}
skvm::F32 SkLinearGradient::transformT(skvm::Builder* p, skvm::Uniforms*,
- skvm::F32 x, skvm::F32 y, skvm::I32* mask) const {
+ skvm::Coord coord, skvm::I32* mask) const {
// We've baked getting t in x into the matrix, so this is pretty trivial.
- return x;
+ return coord.x;
}
SkShader::GradientType SkLinearGradient::asAGradient(GradientInfo* info) const {
diff --git a/src/shaders/gradients/SkLinearGradient.h b/src/shaders/gradients/SkLinearGradient.h
index c8f9bc6..063b9c5 100644
--- a/src/shaders/gradients/SkLinearGradient.h
+++ b/src/shaders/gradients/SkLinearGradient.h
@@ -30,7 +30,7 @@
SkRasterPipeline* postPipeline) const final;
skvm::F32 transformT(skvm::Builder*, skvm::Uniforms*,
- skvm::F32 x, skvm::F32 y, skvm::I32* mask) const final;
+ skvm::Coord coord, skvm::I32* mask) const final;
private:
SK_FLATTENABLE_HOOKS(SkLinearGradient)
diff --git a/src/shaders/gradients/SkRadialGradient.cpp b/src/shaders/gradients/SkRadialGradient.cpp
index aeefe15..fea9ca6 100644
--- a/src/shaders/gradients/SkRadialGradient.cpp
+++ b/src/shaders/gradients/SkRadialGradient.cpp
@@ -64,8 +64,8 @@
}
skvm::F32 SkRadialGradient::transformT(skvm::Builder* p, skvm::Uniforms*,
- skvm::F32 x, skvm::F32 y, skvm::I32* mask) const {
- return sqrt(x*x + y*y);
+ skvm::Coord coord, skvm::I32* mask) const {
+ return sqrt(coord.x*coord.x + coord.y*coord.y);
}
/////////////////////////////////////////////////////////////////////
diff --git a/src/shaders/gradients/SkRadialGradient.h b/src/shaders/gradients/SkRadialGradient.h
index 7568097..7396bb2 100644
--- a/src/shaders/gradients/SkRadialGradient.h
+++ b/src/shaders/gradients/SkRadialGradient.h
@@ -27,7 +27,7 @@
SkRasterPipeline* postPipeline) const override;
skvm::F32 transformT(skvm::Builder*, skvm::Uniforms*,
- skvm::F32 x, skvm::F32 y, skvm::I32* mask) const final;
+ skvm::Coord coord, skvm::I32* mask) const final;
private:
SK_FLATTENABLE_HOOKS(SkRadialGradient)
diff --git a/src/shaders/gradients/SkSweepGradient.cpp b/src/shaders/gradients/SkSweepGradient.cpp
index 1cd7a05..6256cc6 100644
--- a/src/shaders/gradients/SkSweepGradient.cpp
+++ b/src/shaders/gradients/SkSweepGradient.cpp
@@ -68,9 +68,9 @@
}
skvm::F32 SkSweepGradient::transformT(skvm::Builder* p, skvm::Uniforms* uniforms,
- skvm::F32 x, skvm::F32 y, skvm::I32* mask) const {
- skvm::F32 xabs = abs(x),
- yabs = abs(y),
+ skvm::Coord coord, skvm::I32* mask) const {
+ skvm::F32 xabs = abs(coord.x),
+ yabs = abs(coord.y),
slope = min(xabs, yabs) / max(xabs, yabs);
skvm::F32 s = slope * slope;
@@ -82,9 +82,9 @@
+2.476101927459239959716796875e-2f,
-5.185396969318389892578125e-2f,
+0.15912117063999176025390625f);
- phi = select(xabs < yabs, (1/4.0f) - phi, phi);
- phi = select( x < 0.0f, (1/2.0f) - phi, phi);
- phi = select( y < 0.0f, (1/1.0f) - phi, phi);
+ phi = select( xabs < yabs, (1/4.0f) - phi, phi);
+ phi = select(coord.x < 0.0f, (1/2.0f) - phi, phi);
+ phi = select(coord.y < 0.0f, (1/1.0f) - phi, phi);
skvm::F32 t = select(is_NaN(phi), p->splat(0.0f)
, phi);
diff --git a/src/shaders/gradients/SkSweepGradient.h b/src/shaders/gradients/SkSweepGradient.h
index e7beae2..86ca372 100644
--- a/src/shaders/gradients/SkSweepGradient.h
+++ b/src/shaders/gradients/SkSweepGradient.h
@@ -31,7 +31,7 @@
SkRasterPipeline* postPipeline) const override;
skvm::F32 transformT(skvm::Builder*, skvm::Uniforms*,
- skvm::F32 x, skvm::F32 y, skvm::I32* mask) const final;
+ skvm::Coord coord, skvm::I32* mask) const final;
private:
SK_FLATTENABLE_HOOKS(SkSweepGradient)
diff --git a/src/shaders/gradients/SkTwoPointConicalGradient.cpp b/src/shaders/gradients/SkTwoPointConicalGradient.cpp
index 42b3d6f..d3ec755 100644
--- a/src/shaders/gradients/SkTwoPointConicalGradient.cpp
+++ b/src/shaders/gradients/SkTwoPointConicalGradient.cpp
@@ -234,11 +234,13 @@
}
skvm::F32 SkTwoPointConicalGradient::transformT(skvm::Builder* p, skvm::Uniforms* uniforms,
- skvm::F32 x, skvm::F32 y, skvm::I32* mask) const {
+ skvm::Coord coord, skvm::I32* mask) const {
// See https://skia.org/dev/design/conical, and onAppendStages() above.
// There's a lot going on here, and I'm not really sure what's independent
// or disjoint, what can be reordered, simplified, etc. Tweak carefully.
+ const skvm::F32 x = coord.x,
+ y = coord.y;
if (fType == Type::kRadial) {
float denom = 1.0f / (fRadius2 - fRadius1),
scale = std::max(fRadius1, fRadius2) * denom,
diff --git a/src/shaders/gradients/SkTwoPointConicalGradient.h b/src/shaders/gradients/SkTwoPointConicalGradient.h
index a8893ce..d362ba0 100644
--- a/src/shaders/gradients/SkTwoPointConicalGradient.h
+++ b/src/shaders/gradients/SkTwoPointConicalGradient.h
@@ -70,7 +70,7 @@
SkRasterPipeline* postPipeline) const override;
skvm::F32 transformT(skvm::Builder*, skvm::Uniforms*,
- skvm::F32 x, skvm::F32 y, skvm::I32* mask) const final;
+ skvm::Coord coord, skvm::I32* mask) const final;
private:
SK_FLATTENABLE_HOOKS(SkTwoPointConicalGradient)
diff --git a/src/sksl/SkSLByteCode.cpp b/src/sksl/SkSLByteCode.cpp
index b734db5..132dc6d 100644
--- a/src/sksl/SkSLByteCode.cpp
+++ b/src/sksl/SkSLByteCode.cpp
@@ -110,6 +110,7 @@
break;
case ByteCodeInstruction::kLoadExtendedUniform: printf("loadextendeduniform %d", READ8());
break;
+ case ByteCodeInstruction::kLoadFragCoord: printf("loadfragcoord"); break;
case ByteCodeInstruction::kMatrixToMatrix: {
int srcCols = READ8();
int srcRows = READ8();
@@ -926,11 +927,6 @@
}
}
- case ByteCodeInstruction::kSampleExplicit:
- case ByteCodeInstruction::kSampleMatrix:
- // TODO: Support these?
- return false;
-
case ByteCodeInstruction::kScalarToMatrix: {
int cols = READ8();
int rows = READ8();
@@ -1105,6 +1101,14 @@
*loopPtr &= ~m;
continue;
}
+
+ case ByteCodeInstruction::kLoadFragCoord:
+ case ByteCodeInstruction::kSampleExplicit:
+ case ByteCodeInstruction::kSampleMatrix:
+ default:
+ // TODO: Support these?
+ SkASSERT(false);
+ return false;
}
}
}
diff --git a/src/sksl/SkSLByteCode.h b/src/sksl/SkSLByteCode.h
index a4b0918..79f2bef 100644
--- a/src/sksl/SkSLByteCode.h
+++ b/src/sksl/SkSLByteCode.h
@@ -78,6 +78,8 @@
kLoadExtended,
kLoadExtendedGlobal,
kLoadExtendedUniform,
+ // Loads "sk_FragCoord" [X, Y, Z, 1/W]
+ kLoadFragCoord,
// Followed by four bytes: srcCols, srcRows, dstCols, dstRows. Consumes the src matrix from the
// stack, and replaces it with the dst matrix. Per GLSL rules, there are no restrictions on
// dimensions. Any overlapping values are copied, and any other values are filled in with the
@@ -275,7 +277,7 @@
* Some byte code programs can't be executed by the interpreter, due to unsupported features.
* They may still be used to convert to other formats, or for reflection of uniforms.
*/
- bool canRun() const { return fChildFPCount == 0; }
+ bool canRun() const { return fChildFPCount == 0 && !fUsesFragCoord; }
private:
ByteCode(const ByteCode&) = delete;
@@ -287,6 +289,7 @@
int fGlobalSlotCount = 0;
int fUniformSlotCount = 0;
int fChildFPCount = 0;
+ bool fUsesFragCoord = false;
std::vector<Uniform> fUniforms;
std::vector<std::unique_ptr<ByteCodeFunction>> fFunctions;
diff --git a/src/sksl/SkSLByteCodeGenerator.cpp b/src/sksl/SkSLByteCodeGenerator.cpp
index 1d8f87f..819a1a3 100644
--- a/src/sksl/SkSLByteCodeGenerator.cpp
+++ b/src/sksl/SkSLByteCodeGenerator.cpp
@@ -207,10 +207,27 @@
return result;
}
+// If the expression is a reference to a builtin global variable, return the builtin ID.
+// Otherwise, return -1.
+static int expression_as_builtin(const Expression& e) {
+ if (e.fKind == Expression::kVariableReference_Kind) {
+ const Variable& var(((VariableReference&)e).fVariable);
+ if (var.fStorage == Variable::kGlobal_Storage) {
+ return var.fModifiers.fLayout.fBuiltin;
+ }
+ }
+ return -1;
+}
+
// A "simple" Swizzle is based on a variable (or a compound variable like a struct or array), and
// that references consecutive values, such that it can be implemented using normal load/store ops
// with an offset. Note that all single-component swizzles (of suitable base types) are simple.
static bool swizzle_is_simple(const Swizzle& s) {
+ // Builtin variables use dedicated instructions that don't allow subset loads
+ if (expression_as_builtin(*s.fBase) >= 0) {
+ return false;
+ }
+
switch (s.fBase->fKind) {
case Expression::kFieldAccess_Kind:
case Expression::kIndex_Kind:
@@ -366,6 +383,7 @@
case ByteCodeInstruction::kLoadGlobal4:
case ByteCodeInstruction::kLoadUniform4:
case ByteCodeInstruction::kReadExternal4:
+ case ByteCodeInstruction::kLoadFragCoord:
return 4;
case ByteCodeInstruction::kDupN:
@@ -1015,6 +1033,19 @@
}
void ByteCodeGenerator::writeVariableExpression(const Expression& expr) {
+ if (int builtin = expression_as_builtin(expr); builtin >= 0) {
+ switch (builtin) {
+ case SK_FRAGCOORD_BUILTIN:
+ this->write(ByteCodeInstruction::kLoadFragCoord);
+ fOutput->fUsesFragCoord = true;
+ break;
+ default:
+ fErrors.error(expr.fOffset, "Unsupported builtin");
+ break;
+ }
+ return;
+ }
+
Location location = this->getLocation(expr);
int count = SlotCount(expr.fType);
if (count == 0) {
diff --git a/tests/SkRuntimeEffectTest.cpp b/tests/SkRuntimeEffectTest.cpp
index 082a98a..7fdf421 100644
--- a/tests/SkRuntimeEffectTest.cpp
+++ b/tests/SkRuntimeEffectTest.cpp
@@ -76,7 +76,7 @@
}
void test(skiatest::Reporter* r, sk_sp<SkSurface> surface,
- uint32_t TL, uint32_t TR, uint32_t BL, uint32_t BR) {
+ uint32_t TL, uint32_t TR, uint32_t BL, uint32_t BR, SkScalar rotate = 0.0f) {
auto shader = fBuilder->makeShader(nullptr, false);
if (!shader) {
REPORT_FAILURE(r, "shader", SkString("Effect didn't produce a shader"));
@@ -86,6 +86,7 @@
SkPaint paint;
paint.setShader(std::move(shader));
paint.setBlendMode(SkBlendMode::kSrc);
+ surface->getCanvas()->rotate(rotate);
surface->getCanvas()->drawPaint(paint);
uint32_t actual[4];
@@ -153,11 +154,8 @@
// Test sk_FragCoord, which we output to color. Since the surface is 2x2, we should see
// (0,0), (1,0), (0,1), (1,1), multiply by 0.498 to make sure we're not saturating unexpectedly.
- // TODO: Remove this when sk_FragCoord is supported by interpreter.
- if (context) {
- TestEffect fragCoord(r, "", "color = half4(0.498 * (half2(sk_FragCoord.xy) - 0.5), 0, 1);");
- fragCoord.test(r, surface, 0xFF000000, 0xFF00007F, 0xFF007F00, 0xFF007F7F);
- }
+ TestEffect fragCoord(r, "", "color = half4(0.498 * (half2(sk_FragCoord.xy) - 0.5), 0, 1);");
+ fragCoord.test(r, surface, 0xFF000000, 0xFF00007F, 0xFF007F00, 0xFF007F7F, 45.0f);
}
DEF_TEST(SkRuntimeEffectSimple, r) {