Анализ форматов вершин

Вы можете диагностировать несколько возможных проблем с производительностью, связанных с вершинами, с помощью профилирования кадров. Используйте панель «Команды» , чтобы просмотреть все вызовы отрисовки, выполняемые вашей игрой в данном кадре, а также количество примитивов, нарисованных на каждый вызов отрисовки. Это может дать приблизительное общее количество вершин, представленных в одном кадре.

Представление профилирования кадров для вызова glDrawElements, при наведении курсора мыши отображаются подробные сведения о параметрах вызова отрисовки.
Рис. 1. Представление профилирования кадра для одного вызова glDrawElements , показывающее 2718 нарисованных треугольных примитивов.

Сжатие атрибутов вершин

Одной из распространенных проблем, с которыми может столкнуться ваша игра, является большой средний размер вершин. Большое количество вершин, отправленных с высоким средним размером вершин, приводит к большой пропускной способности чтения памяти вершин при чтении графическим процессором.

Чтобы наблюдать формат вершин для данного вызова отрисовки, выполните следующие шаги:

  1. Выберите интересующий розыгрыш.

    Это может быть типичный вызов отрисовки сцены, вызов отрисовки с большим количеством вершин, вызов отрисовки сложной модели персонажа или вызов отрисовки какого-либо другого типа.

  2. Перейдите на панель «Конвейер» и щелкните IA для входной сборки. Это определяет формат вершин для вершин, поступающих в графический процессор.

  3. Обратите внимание на ряд атрибутов и их форматы; например, R32G32B32_SFLOAT — это 3-компонентное 32-битное число с плавающей запятой со знаком.

Представление профилирования кадра для входной сборки вызова отрисовки с несжатыми атрибутами вершин.
Рисунок 2. Входная сборка для вызова отрисовки с несжатыми атрибутами, в результате чего размер вершины составляет 56 байт.

Часто атрибуты вершин можно сжать с минимальным снижением качества рисуемых моделей. В частности, мы рекомендуем:

  • Сжатие положения вершины до 16-битных чисел с плавающей запятой половинной точности.
  • Сжатие координат UV-текстуры в 16-битные целые числа без знака.
  • Сжатие касательного пространства путем кодирования нормальных, касательных и бинормальных векторов с использованием кватернионов.

Другие разные атрибуты также могут рассматриваться для типов с более низкой точностью в каждом конкретном случае.

Разделение потока вершин

Вы также можете проверить, правильно ли разделены потоки атрибутов вершин. В архитектурах мозаичного рендеринга, таких как мобильные графические процессоры, позиции вершин сначала используются в проходе объединения для создания ячеек примитивов, обрабатываемых в каждом тайле. Если атрибуты вершин чередуются в одном буфере, все данные вершин считываются в кэш для объединения, даже если используются только позиции вершин.

Чтобы уменьшить пропускную способность памяти чтения вершин и повысить эффективность кэша и, таким образом, сократить время, затрачиваемое на проход объединения, данные вершин следует разделить на два отдельных потока: один для позиций вершин, а другой для всех других атрибутов вершин.

Чтобы выяснить, правильно ли разделены атрибуты вершин:

  1. Выберите интересующий вызов розыгрыша и запишите номер вызова розыгрыша.

    Это может быть типичный вызов отрисовки сцены, вызов отрисовки с большим количеством вершин, вызов отрисовки сложной модели персонажа или вызов отрисовки какого-либо другого типа.

  2. Перейдите на панель «Конвейер» и щелкните IA для входной сборки. Это определяет формат вершин для вершин, поступающих в графический процессор.

  3. Обратите внимание на привязки атрибутов вершин; обычно они могут увеличиваться линейно (0, 1, 2, 3 и т. д.), но это не всегда так. Позиция вершины обычно указывается первым атрибутом вершины в списке.

  4. На панели «Состояние» найдите LastDrawInfos и разверните соответствующий номер вызова отрисовки. Затем разверните BoundVertexBuffers для этого вызова отрисовки.

  5. Наблюдайте за буферами вершин, связанными во время данного вызова отрисовки, с индексами, соответствующими предыдущим привязкам атрибутов вершин.

  6. Расширьте привязки для атрибутов вершин вашего вызова отрисовки и расширьте буферы.

  7. Обратите внимание на VulkanHandle для буферов, которые представляют базовую память, из которой берутся данные вершин. Если VulkanHandle разные, это означает, что атрибуты происходят из разных базовых буферов. Если VulkanHandle одинаковы, но смещения велики (например, больше 100), атрибуты все равно могут происходить из разных подбуферов, но это требует дальнейшего исследования.

Представление профилирования кадра для входной сборки вызова отрисовки и состояние, показывающее привязанный буфер вершин.
Рис. 3. Входная сборка для вызова отрисовки. Панель состояния справа показывает, что атрибуты привязки 0 и 1, положение вершины и нормаль совместно используют один базовый буфер.

Более подробную информацию о разделении потока вершин и о том, как решить эту проблему на различных игровых движках, можно найти в нашем блоге на эту тему.