Унифицированные функции OpenGL — почему так много?

Почему так много функций для настройки Uniforms?

glUniform1f    glUniform2f    glUniform3f    glUniform4f
glUniform1fv   glUniform2fv   glUniform3fv   glUniform4fv
glUniform1i    glUniform2i    glUniform3i    glUniform4i
glUniform1iv   glUniform2iv   glUniform3iv   glUniform4iv
glUniform1ui   glUniform2ui   glUniform3ui   glUniform4ui
glUniform1uiv  glUniform2uiv  glUniform3uiv  glUniform4uiv

glUniformMatrix2fv  glUniformMatrix2x3fv  glUniformMatrix2x4fv
glUniformMatrix3fv  glUniformMatrix3x2fv  glUniformMatrix3x4fv
glUniformMatrix4fv  glUniformMatrix4x2fv  glUniformMatrix4x3fv

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

2

Решение

Задним числом всегда 20/20, и выбор был сделан, чтобы соответствовать другим функциям, которые принимают векторные данные в различных типах и размерности. Я имею в виду glVertex … конечно. Теперь первоначальная причина передачи по значению заключалась в том, что на некоторых архитектурах имеется достаточно регистров, чтобы было эффективнее передавать по значению в регистр. Также компиляторы могут оптимизировать предыдущие операции, чтобы получить правильные значения в правильном регистре.

OpenGL является потомком IrixGL, разработанным SGI для своих графических рабочих станций и операционной системы Irix. Эти рабочие станции использовали архитектуру MIPS. И соглашение о вызовах для MIPS является (https://en.wikipedia.org/wiki/Calling_convention#MIPS)

Наиболее часто используемым [5] соглашением о вызовах для 32-битных MIPS является ABI O32 [6], который передает первые четыре аргумента функции в регистрах $ a0- $ a3; …

ABI N32 и N64 передают первые восемь аргументов функции в регистрах $ a0- $ a7; …

Итак, у вас есть это: на MIPS это довольно разумный выбор для передачи элементов vec4 на значение. Особенно в IrixGL и OpenGL-1.0, где не было массивов вершин, и вам пришлось бы совершать множество вызовов glVertex.

3

Другие решения

Если вы используете современный OpenGL, вы можете использовать Объекты однородного буфера, которые были доступны начиная с OpenGL 3.1.

Тем не менее, требуется немного больше «настройки». В частности, они требуют, чтобы вы создавали свои шейдеры особым образом (определяя единообразные блоки). Вам также необходимо определить макет памяти (std140 является популярным) для блоков или, в качестве альтернативы, запрашивает компоновки, чтобы определить, как должны быть отформатированы данные вашего унифицированного буфера, чтобы привязка соответствовала формату, ожидаемому графическим процессором.

После того, как все настройки выполнены, привязка выполняется с помощью вызова: glBindBuffer(GL_UNIFORM_BUFFER, <name>)так же, как вершины и индексные потоки.

1

Это было отмечено в ходе обсуждения GL_ARB_shader_objects:

15) Существует вероятность огромного взрыва униформы груза.
команды, что делать?

ОБСУЖДЕНИЕ. Нам нужно иметь возможность загружать vec1, vec2, vec3 или vec4, или
массивы vec1, массивы vec2, массивы vec3 или массивы vec4.
Кроме того, необходимо также загружать матрицы 2×2, 3×3 и 4×4,
и массивы 2×2, массивы 3×3 и массивы матриц 4×4. Вход
Значения команд загрузки униформ могут (традиционный OpenGL) входить в
байты, шорты, целые числа, числа с плавающей запятой, двойные и беззнаковые байты, шорты без знака
и неподписанные целые.

РЕШЕНИЕ: предлагаемое подмножество в новых процедурах и функциях
раздел ниже.

Подмножество, о котором идет речь, является тем, которое было ратифицировано:

void Uniform1fARB(int location, float v0)
void Uniform2fARB(int location, float v0, float v1)
void Uniform3fARB(int location, float v0, float v1, float v2)
void Uniform4fARB(int location, float v0, float v1, float v2, float v3)

void Uniform1iARB(int location, int v0)
void Uniform2iARB(int location, int v0, int v1)
void Uniform3iARB(int location, int v0, int v1, int v2)
void Uniform4iARB(int location, int v0, int v1, int v2, int v3)

void Uniform1fvARB(int location, sizei count, const float *value)
void Uniform2fvARB(int location, sizei count, const float *value)
void Uniform3fvARB(int location, sizei count, const float *value)
void Uniform4fvARB(int location, sizei count, const float *value)

void Uniform1ivARB(int location, sizei count, const int *value)
void Uniform2ivARB(int location, sizei count, const int *value)
void Uniform3ivARB(int location, sizei count, const int *value)
void Uniform4ivARB(int location, sizei count, const int *value)

void UniformMatrix2fvARB(int location, sizei count, boolean transpose, const float *value)
void UniformMatrix3fvARB(int location, sizei count, boolean transpose, const float *value)
void UniformMatrix4fvARB(int location, sizei count, boolean transpose, const float *value)

Вызовы беззнаковых целых и неквадратных матриц были добавлены позже.

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

«Следуйте уже установленному API» звучит как более разумное объяснение.


Кроме того, вам действительно нравится передавать типы данных через void * интерфейсы? То, что вы спрашиваете, это как API

glUniform(GLint location, GLenum datatype, GLsizei count, const GLvoid *data)

GL уже полон таких уровней ломкости и небезопасности типов (привет, нетипизированный GLenums!), я бы предпочел API, которые не добавляют больше этого.

1

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

То, что вы спрашиваете, заключается в том, что потенциальные переключатели / если серии реализованы в драйвере GL. Затем вам придется платить за эту стоимость за каждое использование API, даже если приложение уже точно знает, какую форму он собирается установить. Это не будет эффективным дизайном API (несмотря на тот факт, что на самом деле передача буфера униформ в наши дни намного эффективнее. Это было не так, когда разрабатывался этот API).

По этой причине glVertex3f и соавт. был такой дизайн API тоже. Но, по крайней мере, те не генерировали ошибки. Для Uniforms это немного непонятно, поскольку они определенно генерируют ошибки, поэтому код не может быть полностью минимальным.

0
По вопросам рекламы [email protected]