add array to the Uniforms

Note: I have changed from using a byte offset for index to
an ordinary array index at the builder interface, but the
builder converts this to a byte offset for the instruction.
This makes the API easier to use.

I've added pushArray, and pushArrayF to the Uniforms, and
convenience methods on the builder to take Uniforms.

I've expanded the tests to use the new API.

Change-Id: Id538e826a96d4d242ae6482acc711d84c9041239
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/432036
Commit-Queue: Herb Derby <herb@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
This commit is contained in:
Herb Derby 2021-07-23 11:08:25 -04:00 committed by SkCQ
parent 294d687b69
commit a4953515af
3 changed files with 55 additions and 16 deletions

View File

@ -624,8 +624,9 @@ namespace skvm {
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) {
return {this, push(Op::array32, NA,NA,NA,NA, ptr.ix, offset, index)};
return {this, push(Op::array32, NA,NA,NA,NA, ptr.ix, offset, index * sizeof(int))};
}
I32 Builder::splat(int n) { return {this, push(Op::splat, NA,NA,NA,NA, n) }; }

View File

@ -544,6 +544,14 @@ namespace skvm {
}
return {base, (int)( sizeof(int)*(buf.size() - SK_ARRAY_COUNT(ints)) )};
}
Uniform pushArray(int32_t a[]) {
return this->pushPtr(a);
}
Uniform pushArrayF(float a[]) {
return this->pushPtr(a);
}
};
struct PixelFormat {
@ -633,8 +641,12 @@ namespace skvm {
I32 uniform32(Ptr ptr, int offset);
F32 uniformF (Ptr ptr, int offset) { return pun_to_F32(uniform32(ptr,offset)); }
// Load i32/f32 uniform with byte-count offset and index.
// 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) {
return pun_to_F32(array32(ptr, offset, index));
}
// Push and load this color as a uniform.
Color uniformColor(SkColor4f, Uniforms*);
@ -655,6 +667,11 @@ namespace skvm {
I32 gather32 (Uniform u, I32 index) { return this->gather32 (u.ptr, u.offset, index); }
F32 gatherF (Uniform u, I32 index) { return this->gatherF (u.ptr, u.offset, index); }
// Convenience methods for working with array pointers in skvm::Uniforms. Index is an
// array index and not a byte offset. The array pointer is stored at u.
I32 array32 (Uniform a, int index) { return this->array32 (a.ptr, a.offset, index); }
F32 arrayF (Uniform a, int index) { return this->arrayF (a.ptr, a.offset, index); }
// Load an immediate constant.
I32 splat(int n);
I32 splat(unsigned u) { return splat((int)u); }

View File

@ -770,42 +770,63 @@ DEF_TEST(SkVM_NewOps, r) {
}
DEF_TEST(SKVM_array32, r) {
skvm::Builder b;
skvm::Uniforms uniforms(b.uniform(), 0);
// Take up the first slot, so other uniforms are not at 0 offset.
uniforms.push(0);
int i[] = {3, 7};
skvm::Uniform array = uniforms.pushArray(i);
float f[] = {5, 9};
skvm::Uniform arrayF = uniforms.pushArrayF(f);
{
skvm::Ptr buf0 = b.varying<int32_t>(),
buf1 = b.varying<int32_t>(),
uniforms = b.uniform();
buf2 = b.varying<int32_t>();
skvm::I32 x = b.array32(uniforms, 0, 0);
b.store32(buf0, x);
skvm::I32 y = b.array32(uniforms, 0, 4);
b.store32(buf1, y);
skvm::I32 j = b.array32(array, 0);
b.store32(buf0, j);
skvm::I32 k = b.array32(array, 1);
b.store32(buf1, k);
skvm::F32 x = b.arrayF(arrayF, 0);
skvm::F32 y = b.arrayF(arrayF, 1);
b.store32(buf2, b.trunc(b.add(x, y)));
}
test_jit_and_interpreter(b, [&](const skvm::Program& program) {
const int K = 20;
int i[2] = {3, 7};
struct {
int* g;
} uniforms{i};
int32_t buf0[K];
int32_t buf1[K];
const int K = 10;
int32_t buf0[K],
buf1[K],
buf2[K];
program.eval(K, buf0, buf1, &uniforms);
// reset the i[0] for the two tests.
i[0] = 3;
f[1] = 9;
program.eval(K, uniforms.buf.data(), buf0, buf1, buf2);
for (auto v : buf0) {
REPORTER_ASSERT(r, v == 3);
}
for (auto v : buf1) {
REPORTER_ASSERT(r, v == 7);
}
for (auto v : buf2) {
REPORTER_ASSERT(r, v == 14);
}
i[0] = 4;
program.eval(K, buf0, buf1, &uniforms);
f[1] = 10;
program.eval(K, uniforms.buf.data(), buf0, buf1, buf2);
for (auto v : buf0) {
REPORTER_ASSERT(r, v == 4);
}
for (auto v : buf1) {
REPORTER_ASSERT(r, v == 7);
}
for (auto v : buf2) {
REPORTER_ASSERT(r, v == 15);
}
});
}