flatten skvm type nesting

I don't think nesting types in Builder does
anything but make us type Builder:: a lot.

Change-Id: Iaa66a7b5d71cb337f2774688f316e8aa196da55c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/280572
Reviewed-by: Mike Reed <reed@google.com>
Commit-Queue: Mike Klein <mtklein@google.com>
This commit is contained in:
Mike Klein 2020-03-31 12:28:41 -05:00 committed by Skia Commit-Bot
parent adf9d21704
commit 8b99b9e1d1
5 changed files with 67 additions and 67 deletions

View File

@ -425,10 +425,10 @@ namespace skvm {
std::vector<OptimizedInstruction> Builder::optimize(bool for_jit) const { std::vector<OptimizedInstruction> Builder::optimize(bool for_jit) const {
// If requested, first specialize for our JIT backend. // If requested, first specialize for our JIT backend.
auto specialize_for_jit = [&]() -> std::vector<Builder::Instruction> { auto specialize_for_jit = [&]() -> std::vector<Instruction> {
Builder specialized; Builder specialized;
for (int i = 0; i < (int)fProgram.size(); i++) { for (int i = 0; i < (int)fProgram.size(); i++) {
Builder::Instruction inst = fProgram[i]; Instruction inst = fProgram[i];
#if defined(SK_CPU_X86) #if defined(SK_CPU_X86)
switch (Op imm_op; inst.op) { switch (Op imm_op; inst.op) {
@ -478,8 +478,7 @@ namespace skvm {
} }
return specialized.fProgram; return specialized.fProgram;
}; };
const std::vector<Builder::Instruction>& program = for_jit ? specialize_for_jit() const std::vector<Instruction>& program = for_jit ? specialize_for_jit() : fProgram;
: fProgram;
std::vector<bool> live_instructions; std::vector<bool> live_instructions;
std::vector<Val> frontier; std::vector<Val> frontier;
@ -496,7 +495,7 @@ namespace skvm {
auto pressure_change = [&](Val id) -> int { auto pressure_change = [&](Val id) -> int {
int pressure = 0; int pressure = 0;
Builder::Instruction inst = program[id]; Instruction inst = program[id];
// If this is not a sink, then it takes up a register // If this is not a sink, then it takes up a register
if (inst.op > Op::store32) { pressure += 1; } if (inst.op > Op::store32) { pressure += 1; }
@ -550,7 +549,7 @@ namespace skvm {
Val id = frontier.back(); Val id = frontier.back();
frontier.pop_back(); frontier.pop_back();
new_index[id] = i; new_index[id] = i;
Builder::Instruction inst = program[id]; Instruction inst = program[id];
SkASSERT(remaining_uses[id] == 0); SkASSERT(remaining_uses[id] == 0);
// Use the old indices, and fix them up later. // Use the old indices, and fix them up later.
@ -648,7 +647,7 @@ namespace skvm {
return (uint64_t)lo | (uint64_t)hi << 32; return (uint64_t)lo | (uint64_t)hi << 32;
} }
static bool operator==(const Builder::Instruction& a, const Builder::Instruction& b) { bool operator==(const Instruction& a, const Instruction& b) {
return a.op == b.op return a.op == b.op
&& a.x == b.x && a.x == b.x
&& a.y == b.y && a.y == b.y
@ -657,7 +656,7 @@ namespace skvm {
&& a.immz == b.immz; && a.immz == b.immz;
} }
uint32_t Builder::InstructionHash::operator()(const Instruction& inst, uint32_t seed) const { uint32_t InstructionHash::operator()(const Instruction& inst, uint32_t seed) const {
return SkOpts::hash(&inst, sizeof(inst), seed); return SkOpts::hash(&inst, sizeof(inst), seed);
} }
@ -1426,7 +1425,7 @@ namespace skvm {
// - (*live)[id]: notes whether each input instruction is live // - (*live)[id]: notes whether each input instruction is live
// - *sinks: an unsorted set of live instructions with side effects (stores, assert_true) // - *sinks: an unsorted set of live instructions with side effects (stores, assert_true)
// Returns the number of live instructions. // Returns the number of live instructions.
int liveness_analysis(const std::vector<Builder::Instruction>& instructions, int liveness_analysis(const std::vector<Instruction>& instructions,
std::vector<bool>* live, std::vector<bool>* live,
std::vector<Val>* sinks) { std::vector<Val>* sinks) {
int instruction_count = instructions.size(); int instruction_count = instructions.size();
@ -1436,7 +1435,7 @@ namespace skvm {
if (!(*live)[id]) { if (!(*live)[id]) {
(*live)[id] = true; (*live)[id] = true;
liveInstructionCount++; liveInstructionCount++;
Builder::Instruction inst = instructions[id]; Instruction inst = instructions[id];
if (inst.x != NA) { recurse(inst.x, recurse); } if (inst.x != NA) { recurse(inst.x, recurse); }
if (inst.y != NA) { recurse(inst.y, recurse); } if (inst.y != NA) { recurse(inst.y, recurse); }
if (inst.z != NA) { recurse(inst.z, recurse); } if (inst.z != NA) { recurse(inst.z, recurse); }
@ -1483,7 +1482,7 @@ namespace skvm {
return SkMakeSpan(fTable.data() + begin, end - begin); return SkMakeSpan(fTable.data() + begin, end - begin);
} }
Uses::Uses(const std::vector<Builder::Instruction>& instructions, Uses::Uses(const std::vector<Instruction>& instructions,
const std::vector<bool>& liveness) { const std::vector<bool>& liveness) {
int instruction_count = instructions.size(); int instruction_count = instructions.size();
@ -1492,7 +1491,7 @@ namespace skvm {
out_edge_count.resize(instruction_count); out_edge_count.resize(instruction_count);
for (Val id = 0; id < instruction_count; id++) { for (Val id = 0; id < instruction_count; id++) {
if (liveness[id]) { if (liveness[id]) {
Builder::Instruction inst = instructions[id]; Instruction inst = instructions[id];
if (inst.x != NA) { if (inst.x != NA) {
out_edge_count[inst.x] += 1; out_edge_count[inst.x] += 1;
} }
@ -1522,7 +1521,7 @@ namespace skvm {
std::vector<int> edge_cursor{fIndex}; std::vector<int> edge_cursor{fIndex};
for (Val id = 0; id < instruction_count; id++) { for (Val id = 0; id < instruction_count; id++) {
if (liveness[id]) { if (liveness[id]) {
Builder::Instruction inst = instructions[id]; Instruction inst = instructions[id];
if (inst.x != NA) { if (inst.x != NA) {
fTable[edge_cursor[inst.x]] = id; fTable[edge_cursor[inst.x]] = id;
edge_cursor[inst.x] += 1; edge_cursor[inst.x] += 1;

View File

@ -400,6 +400,51 @@ namespace skvm {
explicit operator bool() const { return h && s && l && a; } explicit operator bool() const { return h && s && l && a; }
}; };
struct Uniform {
Arg ptr;
int offset;
};
struct Uniforms {
Arg base;
std::vector<int> buf;
explicit Uniforms(int init) : base(Arg{0}), buf(init) {}
Uniform push(int val) {
buf.push_back(val);
return {base, (int)( sizeof(int)*(buf.size() - 1) )};
}
Uniform pushF(float val) {
int bits;
memcpy(&bits, &val, sizeof(int));
return this->push(bits);
}
Uniform pushPtr(const void* ptr) {
// Jam the pointer into 1 or 2 ints.
int ints[sizeof(ptr) / sizeof(int)];
memcpy(ints, &ptr, sizeof(ptr));
for (int bits : ints) {
buf.push_back(bits);
}
return {base, (int)( sizeof(int)*(buf.size() - SK_ARRAY_COUNT(ints)) )};
}
};
SK_BEGIN_REQUIRE_DENSE
struct Instruction {
Op op; // v* = op(x,y,z,imm), where * == index of this Instruction.
Val x,y,z; // Enough arguments for mad().
int immy,immz; // Immediate bit pattern, shift count, argument index, etc.
};
SK_END_REQUIRE_DENSE
bool operator==(const Instruction&, const Instruction&);
struct InstructionHash {
uint32_t operator()(const Instruction&, uint32_t seed=0) const;
};
struct OptimizedInstruction { struct OptimizedInstruction {
Op op; Op op;
Val x,y,z; Val x,y,z;
@ -412,13 +457,6 @@ namespace skvm {
class Builder { class Builder {
public: public:
SK_BEGIN_REQUIRE_DENSE
struct Instruction {
Op op; // v* = op(x,y,z,imm), where * == index of this Instruction.
Val x,y,z; // Enough arguments for mad().
int immy,immz; // Immediate bit pattern, shift count, argument index, etc.
};
SK_END_REQUIRE_DENSE
Program done(const char* debug_name = nullptr) const; Program done(const char* debug_name = nullptr) const;
@ -477,11 +515,7 @@ namespace skvm {
return bit_cast(gather32(ptr, offset, index)); return bit_cast(gather32(ptr, offset, index));
} }
// Convenience methods for working with skvm::Uniforms. // Convenience methods for working with skvm::Uniform(s).
struct Uniform {
Arg ptr;
int offset;
};
I32 uniform8 (Uniform u) { return this->uniform8 (u.ptr, u.offset); } I32 uniform8 (Uniform u) { return this->uniform8 (u.ptr, u.offset); }
I32 uniform16(Uniform u) { return this->uniform16(u.ptr, u.offset); } I32 uniform16(Uniform u) { return this->uniform16(u.ptr, u.offset); }
I32 uniform32(Uniform u) { return this->uniform32(u.ptr, u.offset); } I32 uniform32(Uniform u) { return this->uniform32(u.ptr, u.offset); }
@ -655,10 +689,6 @@ namespace skvm {
uint64_t hash() const; uint64_t hash() const;
private: private:
struct InstructionHash {
uint32_t operator()(const Instruction& inst, uint32_t seed=0) const;
};
Val push(Op, Val x, Val y=NA, Val z=NA, int immy=0, int immz=0); Val push(Op, Val x, Val y=NA, Val z=NA, int immy=0, int immz=0);
I32 _(I32a x) { I32 _(I32a x) {
@ -697,13 +727,13 @@ namespace skvm {
// - (*live)[id]: notes whether each input instruction is live // - (*live)[id]: notes whether each input instruction is live
// - *sinks: an unsorted set of live instructions with side effects (stores, assert_true) // - *sinks: an unsorted set of live instructions with side effects (stores, assert_true)
// Returns the number of live instructions. // Returns the number of live instructions.
int liveness_analysis(const std::vector<Builder::Instruction>&, int liveness_analysis(const std::vector<Instruction>&,
std::vector<bool>* live, std::vector<bool>* live,
std::vector<Val>* sinks); std::vector<Val>* sinks);
class Uses { class Uses {
public: public:
Uses(const std::vector<Builder::Instruction>&, const std::vector<bool>&); Uses(const std::vector<Instruction>&, const std::vector<bool>&);
// Return an unordered span of Vals which use result of Instruction id. // Return an unordered span of Vals which use result of Instruction id.
SkSpan<const Val> users(Val id) const; SkSpan<const Val> users(Val id) const;
@ -714,35 +744,6 @@ namespace skvm {
std::vector<Val> fTable; std::vector<Val> fTable;
}; };
// Helper to streamline allocating and working with uniforms.
struct Uniforms {
Arg base;
std::vector<int> buf;
explicit Uniforms(int init) : base(Arg{0}), buf(init) {}
Builder::Uniform push(int val) {
buf.push_back(val);
return {base, (int)( sizeof(int)*(buf.size() - 1) )};
}
Builder::Uniform pushF(float val) {
int bits;
memcpy(&bits, &val, sizeof(int));
return this->push(bits);
}
Builder::Uniform pushPtr(const void* ptr) {
// Jam the pointer into 1 or 2 ints.
int ints[sizeof(ptr) / sizeof(int)];
memcpy(ints, &ptr, sizeof(ptr));
for (int bits : ints) {
buf.push_back(bits);
}
return {base, (int)( sizeof(int)*(buf.size() - SK_ARRAY_COUNT(ints)) )};
}
};
using Reg = int; using Reg = int;
// d = op(x, y/imm, z/imm) // d = op(x, y/imm, z/imm)
@ -907,10 +908,10 @@ namespace skvm {
static inline I32 gather32(Arg ptr, int off, I32 ix) { return ix->gather32(ptr, off, ix); } static inline I32 gather32(Arg ptr, int off, I32 ix) { return ix->gather32(ptr, off, ix); }
static inline F32 gatherF (Arg ptr, int off, I32 ix) { return ix->gatherF (ptr, off, ix); } static inline F32 gatherF (Arg ptr, int off, I32 ix) { return ix->gatherF (ptr, off, ix); }
static inline I32 gather8 (Builder::Uniform u, I32 ix) { return ix->gather8 (u, ix); } static inline I32 gather8 (Uniform u, I32 ix) { return ix->gather8 (u, ix); }
static inline I32 gather16(Builder::Uniform u, I32 ix) { return ix->gather16(u, ix); } static inline I32 gather16(Uniform u, I32 ix) { return ix->gather16(u, ix); }
static inline I32 gather32(Builder::Uniform u, I32 ix) { return ix->gather32(u, ix); } static inline I32 gather32(Uniform u, I32 ix) { return ix->gather32(u, ix); }
static inline F32 gatherF (Builder::Uniform u, I32 ix) { return ix->gatherF (u, ix); } static inline F32 gatherF (Uniform u, I32 ix) { return ix->gatherF (u, ix); }
static inline F32 sqrt(F32 x) { return x-> sqrt(x); } static inline F32 sqrt(F32 x) { return x-> sqrt(x); }
static inline F32 approx_log2(F32 x) { return x->approx_log2(x); } static inline F32 approx_log2(F32 x) { return x->approx_log2(x); }

View File

@ -131,7 +131,7 @@ public:
c = p->clamp(c, p->splat(0.f), p->splat(1.0f)); c = p->clamp(c, p->splat(0.f), p->splat(1.0f));
skvm::I32 index = p->to_unorm(8, c); skvm::I32 index = p->to_unorm(8, c);
skvm::Builder::Uniform table = uniforms->pushPtr(bytePtr); skvm::Uniform table = uniforms->pushPtr(bytePtr);
skvm::I32 byte = p->gather8(table, index); skvm::I32 byte = p->gather8(table, index);
return p->from_unorm(8, byte); return p->from_unorm(8, byte);
}; };

View File

@ -730,7 +730,7 @@ skvm::Color SkImageShader::onProgram(skvm::Builder* p, skvm::F32 x, skvm::F32 y,
clamped_y = clamp(sy, pm.height()); clamped_y = clamp(sy, pm.height());
// Load pixels from pm.addr()[(int)sx + (int)sy*stride]. // Load pixels from pm.addr()[(int)sx + (int)sy*stride].
skvm::Builder::Uniform img = uniforms->pushPtr(pm.addr()); skvm::Uniform img = uniforms->pushPtr(pm.addr());
skvm::I32 index = p->add(p->trunc(clamped_x), skvm::I32 index = p->add(p->trunc(clamped_x),
p->mul(p->trunc(clamped_y), p->mul(p->trunc(clamped_y),
p->uniform32(uniforms->push(pm.rowBytesAsPixels())))); p->uniform32(uniforms->push(pm.rowBytesAsPixels()))));

View File

@ -536,7 +536,7 @@ skvm::Color SkGradientShaderBase::onProgram(skvm::Builder* p,
fb[stops.size()] = { 0.0f, color_lo }; fb[stops.size()] = { 0.0f, color_lo };
// We'll gather FBs from that array we just created. // We'll gather FBs from that array we just created.
skvm::Builder::Uniform fbs = uniforms->pushPtr(fb); skvm::Uniform fbs = uniforms->pushPtr(fb);
// Find the two stops we need to interpolate. // Find the two stops we need to interpolate.
skvm::I32 ix; skvm::I32 ix;