10 Nov 2024 |
almindor | I don't mean atm. | 23:53:45 |
almindor | I just realized yesterday that I have write access so happy to go back to redesigning the thing | 23:54:01 |
almindor | but I think we should consider the BE question for e-g as well. It seems to me just defaulting to BE representation in Rgb colors in e-g would be a huge boon, but perhaps I'm not seeing some complications with that | 23:54:47 |
GrantM11235 | I don't think it's even worth trying to fix d-i, it would be much easier to define a trait that just works for all mipi-dcs displays | 23:55:38 |
almindor | that's a way to go too. The best outcome I can imagine is one where the source color data would match expectations of the displays (or at least most of them), the transport layer wouldn't force anything if possible (e.g. if it does need a buffer it'd be const generic settable for example etc.). It also seems, that overall at this level, iterators are just not good | 23:57:51 |
almindor | just using the repeat_n iterator continuous fill approach is over 2x slower than buffering (with same otherwise) | 23:58:15 |
GrantM11235 | Is that due to iterators, or due to d-i's dyn dispatch? | 23:58:39 |
almindor | it's the iterators, I avoided d-i in one case completely | 23:58:53 |
almindor | basically buf = [x, count] is way more performant (even with a small-ish buffer size) than iter repeat | 23:59:19 |
almindor | at least with spi | 23:59:21 |
almindor | it could be due to a Riscv MCU tho, and a small one at that. E.g. no vectoring etc. | 23:59:54 |
11 Nov 2024 |
GrantM11235 | I'm not sure I understand what you tested, do you have some example code lying around? | 00:01:45 |
GrantM11235 | Are you talking about the e-h 0.2 blocking::spi::WriteIter? | 00:04:33 |
almindor | oh no, I was working on https://github.com/almindor/mipidsi/issues/142 and after I managed to squeeze the "full" ~62 FPS out of using a direct buffer -> spi send approach, I started looking into why fill_solid is so slow compared to it | 00:07:58 |
almindor | I expected some slowdown but not that much so I went and did a bunch of things including using your PR for d-i from ages ago (the static dispatch one). What ended up being the big hit tho was just the use of iterator repeat. even the to_be calls aren't much impactful if I drop them it's almost the same number | 00:08:59 |
almindor | if I keep using d-i increasing the internal buffer to something like 512 works somewhat, but it's still ~2x slower than the direct buffer approach | 00:10:05 |
almindor | sadly I didn't save all the things I tried, and they all needed changes in various packages | 00:10:26 |
almindor | so atm. my next steps were:
- add const generic param for the BUFFER_SIZE into d-i (just a quick short term "fix")
- implement fill_solid using
let buf = [raw_value; count] instead of iter::repeat (but this requires the matrix approach, I might end up just doing a macro for it)
| 00:11:30 |
GrantM11235 | Were you testing 1. fill buffer 2. send buffer 3. goto 1 versus 1. fill buffer 2. send buffer 3. goto 2? | 00:11:56 |
almindor | I didn't need to refill the buffer it's fill_solid, it was just keep sending the buffer until the fullscreen is done | 00:13:17 |
GrantM11235 | DataFormat::U8Iter does 1 and 2 internally, whereas I think DataFormat::U8 just does 2 | 00:13:54 |
GrantM11235 | But you said you were just using U8, nvm | 00:14:28 |
almindor | DataFormat::U8 does just dc set high + spi.write (so CS as well) | 00:14:43 |
almindor | so technically there's a loss there, compared to say a huge single buffer, but with a big enough one it's not much noticable | 00:14:58 |
almindor | but I was essentially comparing DataFormat::U8 vs DataFormat::U16BEIter and it's internal buffering thinking the issue was there | 00:16:05 |
almindor | but it turned out, the issue was largely in the original generator of the iter itself | 00:16:19 |
almindor | the internal d-i buffer (64 pixels wide) DOES need a bit of a bump but it's not the main culprit in the end | 00:16:58 |
GrantM11235 | In reply to @grantm11235:matrix.org
Something like this:
pub trait Interface<P: Copy> {
type Error: core::fmt::Debug;
fn send_command(&mut self, command: u8, args: &[u8]) -> Result<(), Self::Error>;
fn send_pixels(&mut self, pixels: impl Iterator<Item = P>) -> Result<(), Self::Error>;
fn send_repeated_pixel(&mut self, pixel: P, count: u32) -> Result<(), Self::Error> {
self.send_pixels((0..count).map(|_| pixel))
}
fn flush(&mut self) -> Result<(), Self::Error>;
}
BTW, the reason this has a repeated pixel command is so that buffered impls like spi can fill their buffer once and reuse it | 00:17:34 |
GrantM11235 | Also, the buffer should be a user-provided &mut [u8] imo | 00:18:19 |
almindor | yes, or we can just use a const generic | 00:18:37 |