Reland "uniform Ptr (UPtr) is a sub class of Ptr"

This is a reland of cef047a490

Fix strides in SkVMTest to be the right size.

Original change's description:
> uniform Ptr (UPtr) is a sub class of Ptr
>
> A pointer for a Uniform (UPtr) is a sub type of a Ptr. Everywhere you
> can use a Ptr a UPtr will work, but you can't use Ptr where you need
> a UPtr. All the UPtr instructions uniformF, gather32, etc are expected
> to be hoisted and therefore loaded only once. While the varyings
> instructions like load32, etc. are expected to remain in the body
> of the loop, and be evaluated each time through the loop.
>
> Change-Id: I4fe6458c2a4614872ed67cda1e81b05ea8a9e69e
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/436297
> Commit-Queue: Herb Derby <herb@google.com>
> Reviewed-by: Brian Osman <brianosman@google.com>

Change-Id: I858fa1224452ec801b6186fede353849edc895b5
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/436564
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Herb Derby <herb@google.com>
This commit is contained in:
Herb Derby 2021-08-03 16:43:14 -04:00 committed by SkCQ
parent cc04b6f0bf
commit ea17e2499d
7 changed files with 62 additions and 56 deletions

View File

@ -146,7 +146,7 @@ void SkParticleEffectParams::prepare(const skresources::ResourceProvider* resour
// and after it's populated, the values never need to be touched again.
// The second uniform arg is for things declared as 'uniform' in the SkSL (including the
// built-in declarations of 'dt' and 'effect').
skvm::Uniforms efUniforms(skvm::Ptr{0}, 0);
skvm::Uniforms efUniforms(skvm::UPtr{0}, 0);
auto alloc = std::make_unique<SkArenaAlloc>(0);
std::vector<std::unique_ptr<SkSL::ExternalFunction>> externalFns;
@ -178,8 +178,8 @@ void SkParticleEffectParams::prepare(const skresources::ResourceProvider* resour
}
skvm::Builder b;
skvm::Ptr efUniformPtr = b.uniform(), // aka efUniforms.base
skslUniformPtr = b.uniform();
skvm::UPtr efUniformPtr = b.uniform(), // aka efUniforms.base
skslUniformPtr = b.uniform();
(void)efUniformPtr;
std::vector<skvm::Val> uniformIDs;

View File

@ -658,7 +658,8 @@ std::unique_ptr<SkFilterColorProgram> SkFilterColorProgram::Make(const SkRuntime
/*sampleBlender=*/nullptr);
// Then store the result to the *third* arg ptr
p.store({skvm::PixelFormat::FLOAT, 32, 32, 32, 32, 0, 32, 64, 96}, p.arg(16), result);
p.store({skvm::PixelFormat::FLOAT, 32, 32, 32, 32, 0, 32, 64, 96},
p.varying<skvm::F32>(), result);
if (!allSampleCallsSupported) {
return nullptr;

View File

@ -610,22 +610,22 @@ namespace skvm {
return {this, push(Op::load128, NA,NA,NA,NA, ptr.ix,lane) };
}
I32 Builder::gather8 (Ptr ptr, int offset, I32 index) {
I32 Builder::gather8 (UPtr ptr, int offset, I32 index) {
return {this, push(Op::gather8 , index.id,NA,NA,NA, ptr.ix,offset)};
}
I32 Builder::gather16(Ptr ptr, int offset, I32 index) {
I32 Builder::gather16(UPtr ptr, int offset, I32 index) {
return {this, push(Op::gather16, index.id,NA,NA,NA, ptr.ix,offset)};
}
I32 Builder::gather32(Ptr ptr, int offset, I32 index) {
I32 Builder::gather32(UPtr ptr, int offset, I32 index) {
return {this, push(Op::gather32, index.id,NA,NA,NA, ptr.ix,offset)};
}
I32 Builder::uniform32(Ptr ptr, int offset) {
I32 Builder::uniform32(UPtr ptr, int offset) {
return {this, push(Op::uniform32, NA,NA,NA,NA, ptr.ix, offset)};
}
// Note: this converts the array index into a byte offset for the op.
I32 Builder::array32 (Ptr ptr, int offset, int index) {
I32 Builder::array32 (UPtr ptr, int offset, int index) {
return {this, push(Op::array32, NA,NA,NA,NA, ptr.ix, offset, index * sizeof(int))};
}
@ -1178,7 +1178,7 @@ namespace skvm {
return {};
}
Color Builder::gather(PixelFormat f, Ptr ptr, int offset, I32 index) {
Color Builder::gather(PixelFormat f, UPtr ptr, int offset, I32 index) {
switch (byte_size(f)) {
case 1: return unpack(f, gather8 (ptr, offset, index));
case 2: return unpack(f, gather16(ptr, offset, index));

View File

@ -478,7 +478,12 @@ namespace skvm {
// NA meaning none, n/a, null, nil, etc.
static const Val NA = -1;
// Ptr and UPtr are an index into the registers args[]. The two styles of using args are
// varyings and uniforms. Varyings use Ptr, have a stride associated with them, and are
// evaluated everytime through the loop. Uniforms use UPtr, don't have a stride, and are
// usually hoisted above the loop.
struct Ptr { int ix; };
struct UPtr : public Ptr {};
bool operator!=(Ptr a, Ptr b);
@ -515,14 +520,14 @@ namespace skvm {
};
struct Uniform {
Ptr ptr;
UPtr ptr;
int offset;
};
struct Uniforms {
Ptr base;
UPtr base;
std::vector<int> buf;
Uniforms(Ptr ptr, int init) : base(ptr), buf(init) {}
Uniforms(UPtr ptr, int init) : base(ptr), buf(init) {}
Uniform push(int val) {
buf.push_back(val);
@ -600,14 +605,11 @@ namespace skvm {
std::vector<Instruction> program() const { return fProgram; }
std::vector<OptimizedInstruction> optimize() const;
// Declare an argument with given stride (use stride=0 for uniforms).
// TODO: different types for varying and uniforms?
Ptr arg(int stride);
// Convenience arg() wrappers for most common strides, sizeof(T) and 0.
template <typename T>
Ptr varying() { return this->arg(sizeof(T)); }
Ptr uniform() { return this->arg(0); }
Ptr varying(int stride) { SkASSERT(stride > 0); return this->arg(stride); }
UPtr uniform() { Ptr p = this->arg(0); return UPtr{{p.ix}}; }
// TODO: allow uniform (i.e. Ptr) offsets to store* and load*?
// TODO: sign extension (signed types) for <32-bit loads?
@ -638,13 +640,13 @@ namespace skvm {
I32 load128(Ptr ptr, int lane); // Load 32-bit lane 0-3 of 128-bit value.
// Load i32/f32 uniform with byte-count offset.
I32 uniform32(Ptr ptr, int offset);
F32 uniformF (Ptr ptr, int offset) { return pun_to_F32(uniform32(ptr,offset)); }
I32 uniform32(UPtr ptr, int offset);
F32 uniformF (UPtr ptr, int offset) { return pun_to_F32(uniform32(ptr,offset)); }
// Load i32/f32 uniform with byte-count offset and an c-style array index. The address of
// the element is (*(ptr + byte-count offset))[index].
I32 array32 (Ptr ptr, int offset, int index);
F32 arrayF (Ptr ptr, int offset, int index) {
I32 array32 (UPtr ptr, int offset, int index);
F32 arrayF (UPtr ptr, int offset, int index) {
return pun_to_F32(array32(ptr, offset, index));
}
@ -652,10 +654,10 @@ namespace skvm {
Color uniformColor(SkColor4f, Uniforms*);
// Gather u8,u16,i32 with varying element-count index from *(ptr + byte-count offset).
I32 gather8 (Ptr ptr, int offset, I32 index);
I32 gather16(Ptr ptr, int offset, I32 index);
I32 gather32(Ptr ptr, int offset, I32 index);
F32 gatherF (Ptr ptr, int offset, I32 index) {
I32 gather8 (UPtr ptr, int offset, I32 index);
I32 gather16(UPtr ptr, int offset, I32 index);
I32 gather32(UPtr ptr, int offset, I32 index);
F32 gatherF (UPtr ptr, int offset, I32 index) {
return pun_to_F32(gather32(ptr, offset, index));
}
@ -905,7 +907,7 @@ namespace skvm {
Color load(PixelFormat, Ptr ptr);
void store(PixelFormat, Ptr ptr, Color);
Color gather(PixelFormat, Ptr ptr, int offset, I32 index);
Color gather(PixelFormat, UPtr ptr, int offset, I32 index);
Color gather(PixelFormat f, Uniform u, I32 index) {
return gather(f, u.ptr, u.offset, index);
}
@ -957,6 +959,9 @@ namespace skvm {
}
private:
// Declare an argument with given stride (use stride=0 for uniforms).
Ptr arg(int stride);
Val push(
Op op, Val x=NA, Val y=NA, Val z=NA, Val w=NA, int immA=0, int immB=0, int immC=0) {
return this->push(Instruction{op, x,y,z,w, immA,immB,immC});
@ -1171,10 +1176,10 @@ namespace skvm {
SI void store64 (Ptr ptr, I32 lo, I32 hi) { lo ->store64 (ptr, lo,hi); }
SI void store128(Ptr ptr, I32 x, I32 y, I32 z, I32 w) { x ->store128(ptr, x,y,z,w); }
SI I32 gather8 (Ptr ptr, int off, I32 ix) { return ix->gather8 (ptr, off, ix); }
SI I32 gather16(Ptr ptr, int off, I32 ix) { return ix->gather16(ptr, off, ix); }
SI I32 gather32(Ptr ptr, int off, I32 ix) { return ix->gather32(ptr, off, ix); }
SI F32 gatherF (Ptr ptr, int off, I32 ix) { return ix->gatherF (ptr, off, ix); }
SI I32 gather8 (UPtr ptr, int off, I32 ix) { return ix->gather8 (ptr, off, ix); }
SI I32 gather16(UPtr ptr, int off, I32 ix) { return ix->gather16(ptr, off, ix); }
SI I32 gather32(UPtr ptr, int off, I32 ix) { return ix->gather32(ptr, off, ix); }
SI F32 gatherF (UPtr ptr, int off, I32 ix) { return ix->gatherF (ptr, off, ix); }
SI I32 gather8 (Uniform u, I32 ix) { return ix->gather8 (u, ix); }
SI I32 gather16(Uniform u, I32 ix) { return ix->gather16(u, ix); }
@ -1287,8 +1292,8 @@ namespace skvm {
SI void store(PixelFormat f, Ptr p, Color c) { return c->store(f,p,c); }
SI Color gather(PixelFormat f, Ptr p, int off, I32 ix) { return ix->gather(f,p,off,ix); }
SI Color gather(PixelFormat f, Uniform u , I32 ix) { return ix->gather(f,u,ix); }
SI Color gather(PixelFormat f, UPtr p, int off, I32 ix) { return ix->gather(f,p,off,ix); }
SI Color gather(PixelFormat f, Uniform u , I32 ix) { return ix->gather(f,u,ix); }
SI void premul(F32* r, F32* g, F32* b, F32 a) { a-> premul(r,g,b,a); }
SI void unpremul(F32* r, F32* g, F32* b, F32 a) { a->unpremul(r,g,b,a); }

View File

@ -78,7 +78,7 @@ namespace {
skvm::PixelFormat fmt = skvm::SkColorType_to_PixelFormat(ct);
skvm::Color c = p->load(fmt, p->arg(SkColorTypeBytesPerPixel(ct)));
skvm::Color c = p->load(fmt, p->varying(SkColorTypeBytesPerPixel(ct)));
return SkColorSpaceXformSteps{fSprite, dst}.program(p, uniforms, c);
}
@ -289,7 +289,7 @@ SkVMBlitter::Params SkVMBlitter::EffectiveParams(const SkPixmap& device,
skvm::Color SkVMBlitter::DstColor(skvm::Builder* p, const Params& params) {
skvm::PixelFormat dstFormat = skvm::SkColorType_to_PixelFormat(params.dst.colorType());
skvm::Ptr dst_ptr = p->arg(SkColorTypeBytesPerPixel(params.dst.colorType()));
skvm::Ptr dst_ptr = p->varying(SkColorTypeBytesPerPixel(params.dst.colorType()));
return p->load(dstFormat, dst_ptr);
}
@ -297,7 +297,7 @@ void SkVMBlitter::BuildProgram(skvm::Builder* p, const Params& params,
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) {
// First two arguments are always uniforms and the destination buffer.
uniforms->base = p->uniform();
skvm::Ptr dst_ptr = p->arg(SkColorTypeBytesPerPixel(params.dst.colorType()));
skvm::Ptr dst_ptr = p->varying(SkColorTypeBytesPerPixel(params.dst.colorType()));
// A SpriteShader (in this file) may next use one argument as its varying source.
// Subsequent arguments depend on params.coverage:
// - Full: (no more arguments)
@ -556,7 +556,7 @@ SkVMBlitter::SkVMBlitter(const SkPixmap& device,
bool* ok)
: fDevice(device), fSprite(sprite ? *sprite : SkPixmap{})
, fSpriteOffset(spriteOffset)
, fUniforms(skvm::Ptr{0}, kBlitterUniformsCount)
, fUniforms(skvm::UPtr{{0}}, kBlitterUniformsCount)
, fParams(EffectiveParams(device, sprite, paint, matrices, std::move(clip)))
, fKey(CacheKey(fParams, &fUniforms, &fAlloc, ok)) {}

View File

@ -527,7 +527,7 @@ DEF_TEST(SkSLInterpreterCompound, r) {
auto build = [&](const SkSL::FunctionDefinition* fn) {
skvm::Builder b;
skvm::Ptr uniformPtr = b.uniform();
skvm::UPtr uniformPtr = b.uniform();
skvm::Val uniforms[16];
for (int i = 0; i < 16; ++i) {
uniforms[i] = b.uniform32(uniformPtr, i * sizeof(int)).id;

View File

@ -138,8 +138,8 @@ DEF_TEST(SkVM_LoopCounts, r) {
DEF_TEST(SkVM_gather32, r) {
skvm::Builder b;
{
skvm::Ptr uniforms = b.uniform(),
buf = b.varying<int>();
skvm::UPtr uniforms = b.uniform();
skvm::Ptr buf = b.varying<int>();
skvm::I32 x = b.load32(buf);
b.store32(buf, b.gather32(uniforms,0, b.bit_and(x, b.splat(7))));
}
@ -186,8 +186,8 @@ DEF_TEST(SkVM_gather32, r) {
DEF_TEST(SkVM_gathers, r) {
skvm::Builder b;
{
skvm::Ptr uniforms = b.uniform(),
buf32 = b.varying<int>(),
skvm::UPtr uniforms = b.uniform();
skvm::Ptr buf32 = b.varying<int>(),
buf16 = b.varying<uint16_t>(),
buf8 = b.varying<uint8_t>();
@ -244,8 +244,8 @@ DEF_TEST(SkVM_gathers, r) {
DEF_TEST(SkVM_gathers2, r) {
skvm::Builder b;
{
skvm::Ptr uniforms = b.uniform(),
buf32 = b.varying<int>(),
skvm::UPtr uniforms = b.uniform();
skvm::Ptr buf32 = b.varying<int>(),
buf16 = b.varying<uint16_t>(),
buf8 = b.varying<uint8_t>();
@ -714,8 +714,8 @@ DEF_TEST(SkVM_NewOps, r) {
// Exercise a somewhat arbitrary set of new ops.
skvm::Builder b;
{
skvm::Ptr buf = b.varying<int16_t>(),
uniforms = b.uniform();
skvm::Ptr buf = b.varying<int16_t>();
skvm::UPtr uniforms = b.uniform();
skvm::I32 x = b.load16(buf);
@ -2331,8 +2331,8 @@ DEF_TEST(SkVM_128bit, r) {
{ // Convert RGBA F32 to RGBA 8888, testing 128-bit loads.
skvm::Builder b;
{
skvm::Ptr dst = b.arg( 4),
src = b.arg(16);
skvm::Ptr dst = b.varying(4),
src = b.varying(16);
skvm::Color c = b.load(rgba_ffff, src);
b.store(rgba_8888, dst, c);
@ -2350,8 +2350,8 @@ DEF_TEST(SkVM_128bit, r) {
{ // Convert RGBA 8888 to RGBA F32, testing 128-bit stores.
skvm::Builder b;
{
skvm::Ptr dst = b.arg(16),
src = b.arg( 4);
skvm::Ptr dst = b.varying(16),
src = b.varying(4);
skvm::Color c = b.load(rgba_8888, src);
b.store(rgba_ffff, dst, c);
@ -2425,8 +2425,8 @@ DEF_TEST(SkVM_badpack, reporter) {
// originally with a bad arm64 implementation of pack().
skvm::Builder p;
{
skvm::Ptr uniforms = p.uniform(),
dst = p.varying<uint16_t>();
skvm::UPtr uniforms = p.uniform();
skvm::Ptr dst = p.varying<uint16_t>();
skvm::I32 r = round(p.uniformF(uniforms, 8) * 15),
a = p.splat(0xf);
@ -2484,8 +2484,8 @@ DEF_TEST(SkVM_gather_can_hoist, r) {
// First a typical gather scenario with varying index.
{
skvm::Builder b;
skvm::Ptr uniforms = b.uniform(),
buf = b.varying<int>();
skvm::UPtr uniforms = b.uniform();
skvm::Ptr buf = b.varying<int>();
skvm::I32 ix = b.load32(buf);
b.store32(buf, b.gather32(uniforms,0, ix));
@ -2504,8 +2504,8 @@ DEF_TEST(SkVM_gather_can_hoist, r) {
// Now the same but with a uniform index instead.
{
skvm::Builder b;
skvm::Ptr uniforms = b.uniform(),
buf = b.varying<int>();
skvm::UPtr uniforms = b.uniform();
skvm::Ptr buf = b.varying<int>();
skvm::I32 ix = b.uniform32(uniforms,8);
b.store32(buf, b.gather32(uniforms,0, ix));