Flutter CustomPainter с drawRawPoints все еще имеет низкий FPS (эмулятор Web + Android) для индексированного фреймбуфераAndroid

Форум для тех, кто программирует под Android
Ответить
Anonymous
 Flutter CustomPainter с drawRawPoints все еще имеет низкий FPS (эмулятор Web + Android) для индексированного фреймбуфера

Сообщение Anonymous »

Я визуализирую кадровый буфер размером 128x128 в ретро-стиле во Flutter, используя CustomPainter + Canvas.drawRawPoints.
Я уже удалил покадровое распределение, предварительно распределив типизированные буферы на индекс палитры, но 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;
}
Я также рисую дополнительные наложения (режим сетки/виньетки/шейдера), но низкий FPS происходит даже в основном «идеальном по пикселям» режиме.
Вопросы:
  • Ожидается ли, что drawRawPoints будет таким медленным на эмуляторе Web/Android даже для 128x128?
  • Есть ли лучший подход на основе Flutter для этой рабочей нагрузки (например, drawAtlas, RawImage с обновленной текстурой, SceneBuilder и т. д.)?
  • Известные ошибки при использовании setState в каждом кадре этого шаблона?
Ограничения:
  • Путь рендеринга Pure Dart/Flutter
  • Цель: 60 кадров в секунду.
  • Фиксированный 16-цветный индексированный кадровый буфер.


Подробнее здесь: https://stackoverflow.com/questions/798 ... d-emulator
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Android»