Невозможно создать FBO с более чем 8 буферами рендеринга

Итак, вот проблема. У меня есть FBO с 8 буферами рендеринга, которые я использую в своем конвейере отложенного рендеринга. Затем я добавил еще один буфер рендеринга и теперь получаю ошибку GLError.

GLError(
err = 1282,
description = b'invalid operation',
baseOperation = glFramebufferTexture2D,
cArguments = (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT8, GL_TEXTURE_2D, 12, 0,)

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

glMyRenderBuffer = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, glMyRenderBuffer)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, self.width, self.height, 0, GL_RGB, GL_FLOAT, None)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST)
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT8, GL_TEXTURE_2D, glMyRenderBuffer, 0)
glGenerateMipmap(GL_TEXTURE_2D)

И я получаю ошибку в этой строке

glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT8, GL_TEXTURE_2D, glMyRenderBuffer, 0)

Это больше похоже на какое-то ограничение OpenGL, о котором я не знаю.

А еще у меня странный стек - Linux + GLFW + PyOpenGL, что тоже может быть причиной этой проблемы.

Буду рад любому совету на данный момент.


person user3051029    schedule 11.02.2019    source источник


Ответы (1)


Это больше похоже на какое-то ограничение OpenGL, о котором я не знаю.

Соответствующее ограничение равно GL_MAX_COLOR_ATTACHMENTS, и спецификация гарантирует, что это значение не менее 8.

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

Рассмотрим следующие вещи:

  • постарайтесь максимально уменьшить количество целей рендеринга, не храните избыточную информацию (например, позицию вершины), которую можно легко вычислить на лету (вам нужна только глубина, и обычно у вас в любом случае есть привязка к глубине)
  • используйте умные кодировки, подходящие для данных, т.е. 3xfloat для нормального вектора - огромная трата. См., например, Обзор эффективных представлений для независимых единичных векторов
  • объединить различные цели рендеринга. т. е. если вам нужен один выход vec3 и 2 выхода vec2, лучше используйте 2 цели vec4 и назначьте 8 значений 8 каналам.
  • возможно, даже использовать форматы с более высокой битовой глубиной, такие как RGBA32UI, и вручную кодировать разные значения в один канал.

Если вам все еще нужно больше данных, вы можете сделать несколько проходов рендеринга (в основном с n/8 целями для каждого прохода). Другой альтернативой может быть использование загрузки/хранения изображений или SSBO в фрагментном шейдере для записи дополнительных данных. В вашем сценарии использование загрузки/сохранения изображений кажется наиболее целесообразным, поскольку вам, вероятно, нужны полученные данные в виде текстуры. Вы также получаете относительно хороший шаблон доступа, так как вы можете использовать gl_FragCoord.xy для адресации изображения. Однако следует соблюдать осторожность, если у вас есть перекрывающаяся геометрия в одном вызове отрисовки, чтобы вы записывали в каждый пиксель более одного раза (эта проблема также решается GL_ARB_fragment_shader_interlockрасширение, но это еще не основная функция OpenGL). Однако вы можете полностью исключить этот сценарий, используя предварительный проход глубины.

person derhass    schedule 11.02.2019
comment
›Теперь потребность в более чем 8 целях рендеринга за один проход в любом случае кажется безумием. Это не совсем безумие. Я делаю некоторую научную визуализацию с большим количеством дополнительных данных, таких как сегментация и прочее, и я боюсь, что не могу этого избежать. Но все равно спасибо, я просто хотел убедиться, что этого ограничения не избежать. Я начну изучать такого рода оптимизации и, возможно, небольшую перестройку своего пайплайна. - person user3051029; 11.02.2019
comment
Что ж, в рамках гарантий, которые дает GL (и фактических ограничений HW большинства графических процессоров), вы можете получить 8 целей рендеринга максимум с 4x32-битными каналами. Если вы не можете вместить свои данные в них, вам нужно выполнить несколько проходов рендеринга. Создание динамической системы, в которой n цели рендеринга будут соответствовать n/8 проходам, не будет слишком сложной задачей, вопрос скорее в том, какой уровень производительности все еще приемлем для вашего сценария... - person derhass; 11.02.2019
comment
Я обновил свой ответ, чтобы также упомянуть альтернативу использования загрузки/сохранения изображений. - person derhass; 11.02.2019