support 64-bit gather()
This splits 64-bit PixelFormats into two 32-bit parts and gathers both independently. E.g. F16 = {HALF, 16,16,16,16, 0,16,32,48} ~> lo = {HALF, 16,16, 0, 0, 0,16,32,32} ~> hi = {HALF, 0, 0,16,16, 32,32, 0,16} The logic at the end merges the channels we gather from each part. This all does strongly assume no channel straddles lo/hi, which we assert. We'd need to get more clever to handle something like 20-20-20-4. I'm working on load() and store() now, and they'll need this same format assumption. Since I've so far only added support for gather(), I've introduced a little temporary hack in SkImageShader to let it work just to demo this all. This hack will go away when I add support for load and store. Change-Id: Ic4cfda7922f2e51bb7698adedf6f655de43da630 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/303320 Reviewed-by: Herb Derby <herb@google.com> Commit-Queue: Mike Klein <mtklein@google.com>
This commit is contained in:
parent
7fe0359130
commit
6514832226
@ -1204,12 +1204,43 @@ namespace skvm {
|
||||
return {};
|
||||
}
|
||||
|
||||
static void split_disjoint_8byte_format(PixelFormat f, PixelFormat* lo, PixelFormat* hi) {
|
||||
SkASSERT(byte_size(f) == 8);
|
||||
// We assume some of the channels are in the low 32 bits, some in the high 32 bits.
|
||||
// The assert on byte_size(lo) will trigger if this assumption is violated.
|
||||
*lo = f;
|
||||
if (f.r_shift >= 32) { lo->r_bits = 0; lo->r_shift = 32; }
|
||||
if (f.g_shift >= 32) { lo->g_bits = 0; lo->g_shift = 32; }
|
||||
if (f.b_shift >= 32) { lo->b_bits = 0; lo->b_shift = 32; }
|
||||
if (f.a_shift >= 32) { lo->a_bits = 0; lo->a_shift = 32; }
|
||||
SkASSERT(byte_size(*lo) == 4);
|
||||
|
||||
*hi = f;
|
||||
if (f.r_shift < 32) { hi->r_bits = 0; hi->r_shift = 32; } else { hi->r_shift -= 32; }
|
||||
if (f.g_shift < 32) { hi->g_bits = 0; hi->g_shift = 32; } else { hi->g_shift -= 32; }
|
||||
if (f.b_shift < 32) { hi->b_bits = 0; hi->b_shift = 32; } else { hi->b_shift -= 32; }
|
||||
if (f.a_shift < 32) { hi->a_bits = 0; hi->a_shift = 32; } else { hi->a_shift -= 32; }
|
||||
SkASSERT(byte_size(*hi) == 4);
|
||||
}
|
||||
|
||||
Color Builder::gather(PixelFormat f, Arg 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));
|
||||
case 4: return unpack(f, gather32(ptr, offset, index));
|
||||
// TODO: 8,16
|
||||
case 8: {
|
||||
PixelFormat lo,hi;
|
||||
split_disjoint_8byte_format(f, &lo,&hi);
|
||||
Color l = unpack(lo, gather32(ptr, offset, (index<<1)+0)),
|
||||
h = unpack(hi, gather32(ptr, offset, (index<<1)+1));
|
||||
return {
|
||||
lo.r_bits ? l.r : h.r,
|
||||
lo.g_bits ? l.g : h.g,
|
||||
lo.b_bits ? l.b : h.b,
|
||||
lo.a_bits ? l.a : h.a,
|
||||
};
|
||||
}
|
||||
// TODO: 16
|
||||
default: SkUNREACHABLE;
|
||||
}
|
||||
return {};
|
||||
|
@ -788,12 +788,22 @@ skvm::Color SkImageShader::onProgram(skvm::Builder* p,
|
||||
|
||||
skvm::Coord upperLocal = SkShaderBase::ApplyMatrix(p, upperInv, origLocal, uniforms);
|
||||
|
||||
// We "secretly" know that gather() will work with 64-bit pixel formats
|
||||
// even if SkColorType_to_PixelFormat() returns false.
|
||||
auto temporary_ct_to_pixel_format = [](SkColorType ct, skvm::PixelFormat* f) -> bool {
|
||||
if (ct == kRGBA_F16_SkColorType) {
|
||||
*f = {skvm::PixelFormat::HALF, 16,16,16,16, 0,16,32,48};
|
||||
return true;
|
||||
}
|
||||
return SkColorType_to_PixelFormat(ct, f);
|
||||
};
|
||||
|
||||
// Bail out if sample() can't yet handle our image's color type(s).
|
||||
skvm::PixelFormat unused;
|
||||
if (true && !SkColorType_to_PixelFormat(upper->colorType(), &unused)) {
|
||||
if (true && !temporary_ct_to_pixel_format(upper->colorType(), &unused)) {
|
||||
return {};
|
||||
}
|
||||
if (lower && !SkColorType_to_PixelFormat(lower->colorType(), &unused)) {
|
||||
if (lower && !temporary_ct_to_pixel_format(lower->colorType(), &unused)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
@ -834,7 +844,7 @@ skvm::Color SkImageShader::onProgram(skvm::Builder* p,
|
||||
|
||||
auto setup_uniforms = [&](const SkPixmap& pm) -> Uniforms {
|
||||
skvm::PixelFormat pixelFormat;
|
||||
SkAssertResult(SkColorType_to_PixelFormat(pm.colorType(), &pixelFormat));
|
||||
SkAssertResult(temporary_ct_to_pixel_format(pm.colorType(), &pixelFormat));
|
||||
return {
|
||||
p->uniformF(uniforms->pushF( pm.width())),
|
||||
p->uniformF(uniforms->pushF(1.0f/pm.width())), // iff tileX == kRepeat
|
||||
|
Loading…
Reference in New Issue
Block a user