Я уже удалил покадровое распределение, предварительно распределив типизированные буферы на индекс палитры, но FPS все еще очень низкий в Интернете (~ 12 FPS), а также низкий на эмуляторе Android после тестирования. iOS намного лучше.
Я профилировал цикл движка отдельно, и он кажется достаточно быстрым (шаг моделирования составляет около 1–2 мс на кадр), поэтому это похоже на узкое место в представлении/рендеринге.
Упрощенный код (анонимизированный):
Код: Выделить всё
class FrameScreen extends StatefulWidget {
const FrameScreen({super.key, required this.frames});
final Stream frames;
@override
State createState() => _FrameScreenState();
}
class _FrameScreenState extends State {
final PixelBuckets _pixelBuckets = PixelBuckets();
FrameData? _lastFrame;
StreamSubscription? _sub;
@override
void initState() {
super.initState();
_sub = widget.frames.listen((frame) {
_lastFrame = frame;
_pixelBuckets.update(frame.indices); // 16 color buckets, reused arrays
if (mounted) setState(() {});
});
}
@override
Widget build(BuildContext context) {
if (_lastFrame == null) return const SizedBox.shrink();
return CustomPaint(
painter: PixelPainter(
buckets: _pixelBuckets,
palette: _lastFrame!.palette,
),
child: const SizedBox.expand(),
);
}
}
class PixelPainter extends CustomPainter {
PixelPainter({required this.buckets, required this.palette});
final PixelBuckets buckets;
final List palette;
@override
void paint(Canvas canvas, Size size) {
canvas.scale(size.width / 128, size.height / 128);
final paint = Paint()
..strokeWidth = 1.0
..strokeCap = StrokeCap.square;
for (var i = 0; i < 16; i++) {
final count = buckets.counts[i];
if (count == 0) continue;
paint.color = Color(palette[i]);
final points = Float32List.sublistView(buckets.points[i], 0, count * 2);
canvas.drawRawPoints(ui.PointMode.points, points, paint);
}
}
@override
bool shouldRepaint(covariant PixelPainter oldDelegate) => true;
}
Вопросы:
- Ожидается ли, что drawRawPoints будет таким медленным на эмуляторе Web/Android даже для 128x128?
- Есть ли лучший подход на основе Flutter для этой рабочей нагрузки (например, drawAtlas, RawImage с обновленной текстурой, SceneBuilder и т. д.)?
- Известные ошибки при использовании setState в каждом кадре этого шаблона?
- Путь рендеринга Pure Dart/Flutter
- Цель: 60 кадров в секунду.
- Фиксированный 16-цветный индексированный кадровый буфер.
Подробнее здесь: https://stackoverflow.com/questions/798 ... d-emulator
Мобильная версия