Производительность iOS CGPath

ОБНОВЛЕНИЕ

Я преодолел ограничения компьютерной графики, рисуя все с помощью OpenGL. Еще есть глюки, но пока работает намного-намного быстрее.

Некоторые интересные моменты:

  • GLKView:Это специальное представление для iOS -, и оно очень помогает в настройке контекста OpenGL и цикла рендеринга. Если вы не на iOS, боюсь, вы сами по себе.
  • Точность шейдера:Точность переменных шейдера в текущей версии OpenGL ES (2.0 )составляет 16 -бит . Этого было мало для моих целей, поэтому я эмулировал 32 -битных арифметических операций с парами 16 -битных переменных.
  • GL_LINES:OpenGL ES изначально может рисовать простые линии. Не очень хорошо(без стыков, без заглушек, см. фиолетово-серую линию в верхней части снимка экрана ниже), но чтобы улучшить это, вам придется написать собственный шейдер, преобразовать каждую линию в полосу треугольника и молиться, чтобы это сработало!(предположительно, так поступают браузеры, когда говорят вам, что Canvas2D ускоряется на GPU -)

Example rendering

  • Нарисуйте как можно меньше . Я полагаю, это имеет смысл, но вы часто можете избежать рендеринга вещей, которые, например, находятся за пределами окна просмотра.
  • OpenGL ES имеетнет поддержки заполненных полигонов , так что вам придется тесселировать их самостоятельно.Рассмотрите возможность использования iPhone -GLU:это порт кода MESA, и он довольно хорош, хотя его немного сложно использовать (нет стандартного интерфейса Objective -C ).

Исходный вопрос

Я пытаюсь нарисовать много CGPath (, обычно более 1000 )в методе drawRectмоего представления прокрутки, которое обновляется, когда пользователь перемещает его пальцем. У меня есть такое же приложение на JavaScript для браузера, и я пытаюсь перенести его в родное приложение для iOS.

Тестовый код iOS: (со 100 строковыми операциями, path— предварительно -, сделанный CGMutablePathRef):

- (void) drawRect:(CGRect)rect {
    // Start the timer
    BSInitClass(@"Renderer");
    BSStartTimedOp(@"Rendering");

    // Get the context
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetLineWidth(context, 2.0);
    CGContextSetFillColorWithColor(context, [[UIColor redColor] CGColor]);
    CGContextSetStrokeColorWithColor(context, [[UIColor blueColor] CGColor]);
    CGContextTranslateCTM(context, 800, 800);

    // Draw the points
    CGContextAddPath(context, path);
    CGContextStrokePath(context);

    // Display the elapsed time
    BSEndTimedOp(@"Rendering");
}

. В JavaScript, для справки, код (с 10000 строковыми операциями ):

window.onload = function() {
  canvas = document.getElementById("test");
  ctx = canvas.getContext("2d");

  // Prepare the points before drawing
  var data = [];
  for (var i = 0; i < 100; i++) data.push ({x: Math.random()*canvas.width, y: Math.random()*canvas.height});

  // Draw those points, and write the elapsed time
  var __start = new Date().getTime();
  for (var i = 0; i < 100; i++) {
    for (var j = 0; j < data.length; j++) {
      var d = data[j];
      if (j == 0) ctx.moveTo (d.x, d.y);
      else ctx.lineTo(d.x,d.y)
    }
  }
  ctx.stroke();
  document.write ("Finished in " + (new Date().getTime() - __start) + "ms");
};

. Теперь я гораздо лучше разбираюсь в оптимизации JavaScript, чем в iOS, но после некоторого профилирования кажется, что накладные расходы CGPath абсолютно, невероятно плохи по сравнению с JavaScript. Оба фрагмента работают примерно ната же скоростьна реальном устройстве iOS, а код JavaScript имеет в 100 раз больше строковых операций, чем код Quartz2D!

РЕДАКТИРОВАТЬ :Вот верхняя часть профилировщика времени в инструментах:

Running Time   Self             Symbol Name
6487.0ms       77.8%  6487.0    aa_render
449.0ms        5.3%   449.0     aa_intersection_event
112.0ms        1.3%   112.0     CGSColorMaskCopyARGB8888
73.0ms         0.8%   73.0      objc::DenseMap, objc::DenseMapInfo >::LookupBucketFor(objc_object* const&, std::pair*&) const
69.0ms         0.8%   69.0      CGSFillDRAM8by1
66.0ms         0.7%   66.0      ml_set_interrupts_enabled
46.0ms         0.5%   46.0      objc_msgSend
42.0ms         0.5%   42.0      floor
29.0ms         0.3%   29.0      aa_ael_insert

Насколько я понимаю, это должно быть намного быстрее на iOS, просто потому, что код нативный... Итак, знаете ли вы:

  • ... что я здесь делаю не так?
  • ... и есть ли другое, лучшее решение для рисования такого количества линий в реальном -времени?

Большое спасибо!

6
задан Community 23 May 2017 в 12:07
поделиться