OpenGL - как GLenum представляет собой 32-битное целое число без знака?

Для начала в OpenGL есть 8 типов объектов буфера:

  • GL_ARRAY_BUFFER
  • GL_ELEMENT_ARRAY_BUFFER
  • GL_COPY_READ_BUFFER
  • ...

Это перечисления, точнее, GLenum. Где GLenum - это 32-битное целое число без знака, которое, так сказать, имеет значения до ~ 4,743,222,432.

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

glBindBuffer (GL_ARRAY_BUFFER, Буферы [размер]);

[void glBindBuffer (GLenum target, GLuint buffer)] документация

Мой вопрос в том, что если это перечисление, его единственное значение должно быть 0,1,2,3,4..7 соответственно, так зачем идти до конца и делать его 32-битным целым числом, если оно имеет только значения до 7? Простите за мои знания CS и OpenGL, это кажется неэтичным.


person Jebathon    schedule 29.12.2013    source источник


Ответы (2)


Перечисления используются не только для буферов - везде нужна символьная константа. В настоящее время присвоено несколько тысяч значений перечисления (посмотрите свой GL.h и последний glext.h. Обратите внимание, что производители выделяют свои официальные диапазоны перечисления, чтобы они могли реализовать специфичные для поставщика расширения, не мешая другим, поэтому 32-битное пространство перечисления - неплохая идея. более эффективен, так что это не проблема производительности.

ОБНОВЛЕНИЕ: Как отметил Андон М. Коулман, в настоящее время выделяются только 16-битные диапазоны перечисления. Было бы полезно сделать ссылку на OpenGL Enumerant Allocation Policies, где также есть следующее замечание:

Исторически сложилось так, что значения перечисления для некоторых расширений от одного производителя распределялись блоками по 1000, начиная с блока [102000,102999] и постепенно увеличиваясь. Значения в этом диапазоне не могут быть представлены как 16-разрядные целые числа без знака. Это налагает существенное и ненужное снижение производительности на некоторые реализации. Такие блоки, которые уже были выделены поставщикам, будут оставаться выделенными до тех пор, пока поставщик добровольно не освободит весь блок, но никакие дополнительные блоки в этом диапазоне не будут выделены.

Большинство из них, похоже, было удалено в пользу 16-битных значений, но использовались 32-битные значения. В текущем glext.h все еще можно найти некоторые (устаревшие) перечислители выше 0xffff, например

#ifndef GL_PGI_misc_hints
#define GL_PGI_misc_hints 1
#define GL_PREFER_DOUBLEBUFFER_HINT_PGI   0x1A1F8
#define GL_CONSERVE_MEMORY_HINT_PGI       0x1A1FD
#define GL_RECLAIM_MEMORY_HINT_PGI        0x1A1FE
...
person derhass    schedule 29.12.2013
comment
Так вы говорите, что буферные объекты делят «пространство» с несколькими сотнями других перечислений? - person Jebathon; 30.12.2013
comment
Тем не менее, OpenGL по-прежнему официально использует только младшие 16 бит пространства GLenum для распределения постоянных значений. GLenum - это 32-битный тип, но в ядре и современном расширенном GL только 16 из них могут использоваться. Вот почему вы часто видите повторное использование перечислителя, когда расширение повышается с EXT до ARB, а затем повышается до уровня ядра. Если бы у нас действительно было 32-битное пространство перечисления для работы, тогда в этом действительно не было бы необходимости .. вы могли бы легко дать каждой (часто функционально несовместимой) итерации расширения свой собственный набор дискретных значений констант. - person Andon M. Coleman; 30.12.2013
comment
@BDillan: ну. существует только одно глобальное пространство имен для перечислителей GL. Так что это, вероятно, да на этот вопрос. - person derhass; 30.12.2013
comment
Так что я думаю, что красная книга (8-е издание) уже устарела. Поскольку он говорит, что его 32 бит. OpenGL ускоряется, думаю, я не собираюсь беспокоиться об этих мелких деталях. - person Jebathon; 30.12.2013
comment
@BDillian: Есть разница между размером шрифта и его диапазоном. Тот факт, что GLenum 32-битный, не означает, что в вашем распоряжении полный диапазон 32-битных целых чисел. Точно так же, только потому, что функция, подобная glBindSampler (...), принимает GLuint для идентификации текстурного блока, с которым вы собираетесь его связать (вместо GLenum), не означает, что у вас действительно может быть 4,27 миллиарда единиц изображения текстуры. Я бы не стал читать книгу об этих подробностях, они изложены в официальной спецификации OpenGL, которую вы можете бесплатно прочитать (для любой версии) по адресу: opengl.org/registry - person Andon M. Coleman; 30.12.2013
comment
@ AndonM.Coleman Эти тривиальные вещи привлекают мое внимание - прошу прощения. Из того, как я это увидел, было 0-7 целочисленных значений и 4 миллиарда пробелов, так что это привлекло мое внимание. Я не знал механики того типа, который вы подробно объяснили. Очень внятный ответ! - person Jebathon; 30.12.2013
comment
@BDillan, считайте это своего рода проверкой ошибок, распространенной во многих протоколах связи. Поскольку каждая функция принимает только несколько конкретных перечислений, они могут сообщить об ошибке, если вы случайно вызовете, например. текстурные функции с символическими значениями, связанными с буфером. - person MaKo; 16.06.2015

В любом случае, зачем вам использовать шорт? В какой ситуации вы когда-либо оказались бы, если бы вы даже сэкономили более 8 КБ оперативной памяти (если отчеты о тысяче GLenum верны), используя short или uint8_t вместо GLuint для объявлений перечислений и const? Принимая во внимание потенциальную несовместимость оборудования и потенциальные кроссплатформенные ошибки, которые вы могли бы внести, довольно странно пытаться сохранить что-то вроде 8-килобайтной оперативной памяти даже в контексте оригинального 2-мегабайтного графического оборудования Voodoo3d, не говоря уже о суперкомпьютерных фермах SGL OpenGL. предназначен для.

Кроме того, современное оборудование x86 и GPU выравнивается по 32 или 64 битам за раз, вы фактически остановите работу CPU / GPU, поскольку 24 или 56 бит регистра должны быть обнулены и ЗАТЕМ прочитаны / записаны, тогда как он мог работать со стандартным int, как только он был скопирован. С самого начала OpenGL вычислительные ресурсы имели тенденцию быть более ценными, чем память, в то время как вы могли вносить миллиарды изменений состояния в течение жизни программы, вы экономили бы около 10 КБ ( килобайт) от RAM max, если вы заменили каждое 32-битное перечисление GLuint на uint8_t. Я так стараюсь сейчас не быть излишне циничным, хех.

Например, одна веская причина для таких вещей, как uint18_t и т.п., - это большие буферы данных / алгоритмы, в которых данные соответствуют этой битовой глубине. 1024 ints против 1024 переменных uint8_t в стеке - 8k, собираемся ли мы разделить волосы на 8k? Теперь рассмотрим необработанное растровое изображение 4k размером 4000 * 2500 * 32 бита, мы говорим о нескольких сотнях мегабайт, и это было бы в 8 раз больше, если бы мы использовали 64-битные буферы RGBA вместо стандартных 8-битных буферов RGBA8 или в четыре раза больше. по размеру, если мы использовали 32-битную кодировку RGBA. Умножьте это на количество открытых текстур или сохраненных изображений, и замена небольшого количества операций процессора для всей этой дополнительной памяти имеет смысл, особенно в контексте такого типа работы.

Вот где имеет смысл использовать нестандартный целочисленный тип. Если вы не используете 64-килобайтную машину или что-то в этом роде (например, звуковой сигнал старой школы, удачи в использовании OpenGL на этой системе), если вы пытаетесь сэкономить несколько бит памяти на чем-то вроде объявления const или счетчика ссылок, вы просто тратить время зря.

person Russell Barlow    schedule 16.06.2015