Різниця між “буфером” та “масивом” у OpenGL?


12

Коли я читаю doc на webGL або OpenGL, то можна побачити деякі шаблони в застосуванні назв функцій та об'єктів. Але я не можу зрозуміти різницю між об'єктом буфера та масивом.

Існують "об'єкти вершинного буфера", "об'єкти вершинного масиву" і навіть якийсь "буферний масив" або "масив буфера".

У OpenGL-контексті, коли щось є "масивом" і коли його слід називати "буфером"?


Деякі перспективи, думають про отримання даних по мережі та зберігання журналу всього отриманого. Вам потрібно прочитати сокет і покласти отримані дані кудись, щоб ви могли їх передавати, це буфер. Часто це може бути просто місцевий, динамічно виділений простий тип списку. Іноді це так просто, як char* buffer = socketRead();(псевдокод). З іншого боку, журнал проживає весь життєвий цикл програми. Таким чином, ви десь створюєте масив і починаєте читати сокет, щоразу, коли ви отримуєте дані, які ви записуєте цей фрагмент до масиву, надаючи чіткий список усіх отриманих даних.
Кевін

Відповіді:


5

Іменування об’єкта Vertex Array є якось невдалим. Існує три різні речі, які з'являються (раніше з'являлися) в / з вашою програмою, і які (історично) були названі по-різному, з назвою "масив" або "буфер" (ну, також є об'єкти фреймбуфера, але я це проігнорую).

  1. Дані, які існують у вашій програмі, формально і фактично, але які виводяться OpenGL за один раз (на відміну від вершин за вершиною). Це було колись, що ви б назвали вершинним масивом .
    Намір цього полягав у тому, щоб зробити доступ більш ефективним, оскільки OpenGL міг просто скопіювати все за один раз у чітко визначений час, коли ви давали обіцянку, що дані будуть узгоджені, і надсилати їх через AGP або що-небудь в одному блоці. Цього більше не існує.
  2. Дані затьмарені та доступні ручкою, яку можна "прив'язати", тобто зробити активною. Дані можуть фактично жити в основній пам'яті або на графічній карті, або переміщуватися в область PCIe-карта, що завгодно, але в будь-якому випадку формально ви не володієте (навіть якщо це фізично в оперативній пам'яті і якщо дані надійшли з вашої програми ) це - якщо ви зараз не "нанесли" його на карту за допомогою відповідного API, повертаючи вказівний (а іноді і читабельний) покажчик. Ви також обмежені у своїх можливостях взагалі контролювати те, що відбувається з даними (ви можете дати підказки, але це майже все).
    OpenGL може переміщувати ці дані навколо або більш вільно, і вам дозволяється копіювати в / з буфера лише через відповідний API або отримати доступ до даних під час їх відображення. Це те, що ви називаєте буферним об'єктом ( об'єкт вершинного буфера, якщо він містить вершини, але він справді не повинен, він також може бути даними зображень або обмундируваннями, тільки вершини були першими, які були підтримані один раз).
    Метою цього є гарантувати, що OpenGL може (в принципі) робити все, що завгодно, він навіть може спекулятивно натискати на буфер над PCIe, перш ніж ви навіть малюєте. Це працює, тому що ви не володієте даними (OpenGL робить!), І ви можете отримати доступ до них лише через даний API, тому завжди відомо, що дані є дійсними. Водій може навіть вирішити викинути буферну пам’ять на відеокарту, коли їй потрібна пам'ять для чогось іншого, а пізніше відновити її з її секретної копії, коли це буде потрібно.
  3. Дійсно дурне неправильне слово, для якого набагато кращою назвою було б щось на зразок буферного набору чи набору дескрипторів, це сумнозвісний об’єкт вершинного масиву . З вашої точки зору, це не що інше, як набір ручок буфера, зібраних разом під іншою незрозумілою ручкою (яку ви можете зв'язати). Як це буває, реальність дещо складніша. Насправді VAO набагато ближче до того, як працює власне обладнання. Графічні картки мають невелику кількість (часто щось на зразок 2, 4 або 8) наборів дескрипторів (не тільки для буферів, але і для пробовідбірників) з таким-таки-багатьма записами в кожному, між якими вони можуть перемикатися дуже ефективно .
    Тепер завданням вершинного масиву є зменшення кількості викликів API та зменшення кількості перевірок узгодженості, які OpenGL повинен робити внутрішньо, і, звичайно, використовувати апаратне забезпечення як працює. Якщо ви прив'язуєте 5 буферів, то кожен повинен пройти кілька можливих дорогих перевірок, і кожен з них є кандидатом на помилки кеша в драйвері, плюс кожен один вимагає спілкування з графічною карткою, щоб змінити дескриптор тощо. Якщо ви замість цього прив’язавши один VAO, драйвер може (часто) просто переключити дескриптор, встановлений на відеокарті, і зробити це.

8

Об'єкт масиву Vertex (VAO) - це об'єкт, який містить один або більше об'єктів буферних вершин і призначений для зберігання інформації для повного виведеного об'єкта.

(витягнуто з хроноса )

Кожен буфер прагне становити один атрибут вершинного масиву (об'єкта). VAO може містити багато вершинних атрибутів (наприклад, положення, колір, УФ). Кожен може міститись у власному буфері, де буфер вказує на неформатовану серію суміжних байтів, і де потрібно чітко вказати розмір (тип) для кожного елемента буфера як для викликів OpenGL на стороні процесора, так і для роботи шейдера на стороні GPU.

Це один спосіб. Інші способи роботи це:

  • Усі атрибути зберігаються переплетеними в одному буфері АБО
  • Деякі з атрибутів існують у власних виділених буферах, а інші діляться буферами.

Наведена нижче схема ілюструє ці два останні випадки.

введіть тут опис зображення

Підсумок: Якщо словосполучення "вершинний масив" в OpenGL використовується некваліфіковане, можна припустити, що воно означає VAO, що в контексті OpenGL (конкретно) - це зовсім інша річ від буфера.

EDIT за ваш коментар: GL_ARRAY_BUFFERвказує намір використовувати цей буферний об’єкт для даних атрибутів вершин, як описано вище. Це тому, що буфери не використовуються лише для атрибутів вершин. Однак, оскільки це найчастіший випадок використання, і ви запитуєте про VAO, я не буду вникати в інші; однак тут є список інших типів буферів, які можна налаштувати.


Таким чином буфери : 1.розміщуються в GPU, 2.більшу частину часу містять один вид даних (лише вершина, лише кольоровий ect), 3.Data перемежовується, тобто 111122223333 ect. 4. не надайте ніякого способу доступу до даних (не буфер [2] або буфер [vertex_3434]). Тепер масивами є: 1.колекція буферів, 2. зберігати інформацію про те, як розбирати буфери, які вони містять. , розмір елемента, компенсації, тому дані з буферів можна отримати правильно. Так?
coobit

1. Буфери існують на обох кінцях і передаються між процесором та графічним процесором (потенційно назад і назад), інакше як би ви заповнили дані для завантаження в GPU при завантаженні сітки з диска ?. Так, елементи мають однаковий тип у всьому буфері, але залежно від технології, яку ви використовуєте, кожен буферний елемент може бути або примітивним, або structтиповим. Дані можуть бути переплетеними або бути повністю однаковими за кожний буфер. Ви можете індексувати їх, як і традиційний масив C на процесорі. Об'єкти масиву (використовуйте цю правильну термінологію або збивайте з себе плутанину!) ... (продовження нижче)
Інженер

2. Так, і вам потрібно чітко переконатися, що ваші декларації в буферних шейдерах відповідатимуть тим специфікаціям, які ви встановили на вашому VAO на стороні процесора. об’єкт масиву. " (khronos docs)
інженер

Отож, просто більше вдарити нігтя ... Як люди працювали до АО лише за допомогою БО? Або AO завжди були присутні у OpenGL, і це лише VAO, який було представлено пізніше, ніж VBO?
coobit

@coobit io7m.com/documents/history-vertex-spec - це дає уявлення про відмінності між фіксованим трубопроводом (старі школи) OpenGL, 3Dfx тощо та сучасним програмованим конвеєром OpenGL та Direct3D.
Інженер

5

Ця термінологія входить в історію OpenGL. Важливо пам’ятати, що для більшості версій GL, які є актуальними тут, OpenGL розвивався поступово і додаючи нову функціональність до вже існуючого API, а не змінюючи API.

Перша версія OpenGL не мала жодного з цих типів об'єктів. Малювання було досягнуто шляхом видачі декількох викликів glBegin / glEnd, і однією з проблем цієї моделі було те, що вона була дуже неефективною, з точки зору накладних викликів функцій.

OpenGL 1.1 зробив перші кроки для вирішення цього питання, ввівши вершинні масиви. Замість того, щоб безпосередньо вказувати дані вершини, тепер ви можете їх джерело з масивів C / C ++ - звідси і назва. Отже, вершинний масив - це саме те - це масив вершин і стан GL, необхідний для їх визначення.

Наступна основна еволюція відбулася з GL 1.5 і дозволила зберігати дані вершинного масиву в пам'яті GPU, а не в системній ("клієнтській") пам'яті. Слабкою специфікацією вершинного масиву GL 1.1 було те, що повний набір вершинних даних повинен був передаватися GPU кожен раз, коли ви хотіли ним користуватися; якби це вже було на GPU, то цього перенесення можна було б уникнути та досягти потенційного підвищення продуктивності.

Так створено новий тип об'єкта GL, який дозволяє зберігати ці дані в GPU. Так само, як текстурний об'єкт використовується для зберігання текстурних даних, об’єкт вершинного буфера зберігає дані вершини. Це насправді лише окремий випадок більш загального типу об'єкта буфера, який може зберігати неспецифічні дані.

API для використання вершинних буферних об'єктів був підкріплений на вже існуючих вершинах API масивів вершин, тому ви бачите дивні речі, такі як перетворення зміщення байтів у покажчики в ньому. Отже, тепер у нас є вершинний масив API, який просто зберігає стан, дані отримуються з буферних об'єктів, а не з масивів пам'яті.

Це доводить нас майже до кінця нашої історії. Отриманий API був досить багатослівним, коли мова зайшла про вказівку стану вершинного масиву, тому інший шлях оптимізації полягав у створенні нового типу об'єкта, який збирав би весь цей стан разом, дозволяв кілька змін стану вершинного масиву в одному виклику API та дозволяв GPU потенційно здійснювати оптимізацію через те, що зможеш знати, який стан буде використаний достроково.

Введіть об’єкт вершинного масиву, який збирає все це разом.

Отже, підводячи підсумок, вершиновий масив розпочав життя як сукупність стану та даних (що зберігаються в масиві) для малювання. Буфер вершин замінює зберігання масиву в пам'яті з типом об'єкта GL, залишаючи масив вершин просто бути станом. Об'єкт масиву вершин просто об'єкт - контейнер для цього стану, що дозволяє йому бути змінений легше і з меншою кількістю викликів API.


0

Я не працював з OpenGL деякий час, тож я міг бути лише напівправим. Взагалі кажучи: буфери зберігають масив неформатованої пам'яті. Масив - це загальний термін суміжної пам'яті.

Буфер повинен бути прив’язаний до контексту, тоді як масив - це лише масив даних. Якщо я пам'ятаю правильно, дані в буфері мають бути скопійовані на відеокарту (звідси прив'язка).

Сподіваюсь, це трохи допомагає


Що тоді GL_ARRAY_BUFFER? Чому його так називали? За
вашою

Ну, саме цей приклад - це лише ідентифікатор буфера (до якого ви прив'язуєте свій масив). Буфер масиву (у вашому прикладі) використовується для атрибутів вершин, тому в основному ви прив'язуєте масив атрибутів вершин до буфера. Звучить заплутано, тому дозвольте навести приклад. У вас є деякий масив на стороні процесора, який може бути кольоровим, нормальним, позицій тощо, і тепер ви хочете, щоб gpu отримав доступ до нього. Ось тоді, коли входить bindBuffer, в основному відображає ваш "cpu-масив" на "gpu-масив".
Juicef

Щодо того, чому його так називали, я не можу відповісти на це. Я б припустив, що це тому, що у вас є масив різних даних, що надходять туди, кольори, звичайні тощо.
Juicef
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.