Как чередующаяся передача вершин помогает производительности?

Я читал и видел другие вопросы, которые, как правило, указывают на предложение чередовать положения и цвета вершин и т. Д. В один массив, поскольку это сводит к минимуму данные, которые передаются из процессора в gpu.

Я не совсем понимаю, как это делает OpenGL, когда даже с чередующимся массивом вы все равно должны делать отдельные вызовы GL для указателей положения и цвета. Если оба указателя используют один и тот же массив, просто настроенный на запуск в разных точках этого массива, разве вызов draw не копирует массив дважды, так как он был объектом двух разных указателей?

3 ответа

Решение

Это в основном о кеше. Например, представьте, что у нас есть 4 вершины и 4 цвета. Вы можете предоставить информацию таким образом (извините, но я не помню точных названий функций)

glVertexPointer(..., vertex);
glColorPointer(..., colors);

То, что он делает внутри, это чтение вершины [0], затем применение цветов [0], затем снова вершина [1] с цветами [1]. Как видите, если длина вершины составляет, например, 20 мегабайт, вершина [0] и цвета [0] будут, по меньшей мере, на расстоянии 20 мегабайт друг от друга.

Теперь, с другой стороны, если вы предоставите такую ​​структуру, как { vertex0, color0, vertex1, color1 и т. Д.}, Будет много попаданий в кэш, потому что, ну, vertex0 и color0 вместе, как и vertex1 и color1.

Надеюсь, это поможет ответить на вопрос

редактировать: во втором чтении, я, возможно, не ответил на вопрос. Возможно, вы задаетесь вопросом, откуда OpenGL знает, какие значения следует читать из этой структуры? Как я уже говорил ранее со структурой, такой как { vertex, color, vertex, color }, вы сообщаете OpenGL, что вершина находится в позиции 0 со смещением 2 (так что следующая будет в позиции 2, затем 4 и т. Д.) И цветом начинается с позиции 1, также со смещением 2 (таким образом, позиция 1, затем 3 и т. д.).

дополнение: если вам нужен более практичный пример, посмотрите эту ссылку http://www.lwjgl.org/wiki/index.php?title=Using_Vertex_Buffer_Objects_(VBO). Вы можете увидеть, как он предоставляет буфер только один раз, а затем использует смещения для эффективной визуализации.

Я предлагаю прочитать: http://www.opengl.org/wiki/Vertex_Specification_Best_Practices

h4lc0n предоставил довольно хорошее объяснение, но я хотел бы добавить дополнительную информацию:

  • чередующиеся данные могут фактически снизить производительность, если ваши данные часто изменяются. Например, когда вы меняете положение точечных спрайтов, вы обновляете POS, но COLOR и TEXCOORD обычно совпадают. Затем, когда данные чередуются, вы должны "прикоснуться" к дополнительным данным. В этом случае было бы лучше иметь один VBO только для POS (или вообще для данных, которые часто меняются) и второй VBO для данных, которые являются постоянными.
  • Нелегко дать строгие правила в отношении компоновки VBO, поскольку она очень специфична для поставщика / драйвера. Также ваше использование может отличаться от других. В общем, необходимо сделать несколько тестов для ваших конкретных тестов

Вы также можете сделать аргумент для разделения различных атрибутов. Предполагая, что графический процессор обрабатывает не одну вершину за другой, а несколько параллельных (например, 16) из них, вы получите что-то подобное при выполнении вершинного шейдера:

  • прочитать атрибут A для всех 16 вершин
  • выполнить некоторые вычисления
  • прочитать атрибут B для всех 16 вершин
  • выполнить еще несколько вычислений
  • ....

Таким образом, вы читаете один атрибут для нескольких вершин одновременно. Из этого рассуждения может показаться, что чередование атрибутов фактически ухудшает производительность. Конечно, это будет видно только в том случае, если вы либо ограничены в пропускной способности, либо если по какой-то причине задержка памяти не может быть скрыта (например, сложный шейдер, который требует много регистров, уменьшит количество вершин, которые могут быть в полете в данный момент времени),

Другие вопросы по тегам