LINUX.ORG.RU

Передать много объектов в Compute Shader

 , , , ,


1

3

Пытаюсь кое-что сделать с compute shaders и появляется вопрос - как передать шейдеру большое количество объектов. Если я правильно понимаю, количество SSBO ограничено GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS (72 в случае моей интеловстройки). (а за что тогда отвечает GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS !?)

Все это осложняется тем, что объекты у меня могут занимать от 4-х байт (теоретический и практический минимум) до 74-х мегабайт.

Еще одна проблема - адресация этих объектов. Каждый из них имеет координату в трехмерном пространстве по которой он должен быть доступен. Как подобное прикрутить к GLSL в котором даже указателей нет - вопрос. К слову, объекты могут быть R/O для шейдера, в них ничего он не пишет, только читает.

Пока что у меня есть пара идей:

  • Рассовывать объекты в UBO и SSBO одновременно в зависимости от их размера (почти половина объектов может влезть в 64кБ, в 16кБ влезет только треть)
  • Динамически генерировать, компилировать (glCompileShader) и линковать с основным шейдером прослойку, которая будет знать обо всех загруженных объектах и предоставлять к ним доступ. Как это эффективно сделать когда нет указателей - вопрос...

Прошу понять, простить идиота, и помочь советом. Доки на khronos.org читал, но не понял.

P.S. объекты являются разреженными октодеревьями, но это, ИМХО, не влияет на проблему.

По первому: GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS - максимальный номер который может принимать binding (тип layout (binding=n) <код>. n < того числа). GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS - максимальное кол-во ssbo в вычислительном шейдере. GL_MAX_SHADER_STORAGE_BLOCK_SIZE - максимальный размер ssbo (The spec guarantees that SSBOs can be up to 128MB. Most implementations will let you allocate a size up to the limit of GPU memory). По второму: Генерируй 3D текстуру, которая будет хранить индексы элементов в одномерном массиве и передавай в шейдер свои объекты через массив. По третьему: UBO работает заметно быстрее чем SSBO. По идеи алгоритм прост, запишиваешь все объекты в один BO. Дальше биндишь часть BO как UBO (по сути массив объектов), и вычисляешь для каждого куска, не забыв подставить туда соответствующую текстуру.

maxis11 ()
Ответ на: комментарий от maxis11

Запихать в один объект (текстуру) все сразу я и так могу, вопрос то в том, как их добавлять/обновлять.

Стоп, а у Opengl были функции которые позволяют записывать со стороны приложения в какую-то область текстуры, не трогая остальное? Тогда может можно огромного объема текстуру заделать и в нее записывать/удалять объекты (своеобразным malloc реализовать)

Я до сих пор в Opengl плаваю как топор в речке, абсолютно запутался с биндингом. Я так понимаю, что объект может быть одним (и большим) а его можно по-кусочкам биндить и как UBO и как SSBO и даже одновременно?

Задумывается все это для рейкастинга (не рейтрейсинга, лучи не отражаются)

Черт его знает как оно по скорости еще выйдет...

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

timdorohin ★★★ ()
Ответ на: комментарий от timdorohin

Стоп, а у Opengl были функции которые позволяют записывать со стороны приложения в какую-то область текстуры, не трогая остальное?

Может быть texture view?

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

С этим все очень плохо. Есть какой-то сборник рецептов шейдеров под ogl 4, переведенный на русский. В остальном все только на английском.

maxis11 ()
Ответ на: комментарий от maxis11

Я тут понял, что каждый кадр (на самом деле далеко не каждый, а только когда «камера» переместится за пределы текущего блока) передавать в видеокарту сто килобайт на производительности сказывается примерно никак, поэтому можно обойтись без глобальной 3д текстуры, а просто из программы генерировать 29х29х29 GL_R32UI на каждое обновление, где точка (15;15;15) всегда будет центром.

И что мне придется наваять свой malloc для запихивания объектов в выделенный буфер. Или, скорее gc_alloc какой-то, чтоб он мог еще оптимизировать и перемещать объекты по своему усмотрению для их уплотнения. Весело, блин.

timdorohin ★★★ ()

GPGPU

Предлагаю рассмотреть такой вариант создается 3D текстура с float значениями. каждое значение - это смещение в 1D текстуре (в 1D текстуре хранятся объекты разного размера, а 3D используется для адресации)

т.е.

uniform sampler3D oct_tree; uniform sampler1D obj_data;

void main(void) { float ofs = texelFetch(oct_tree, vec3(x, y, z)).r; float ofs2; // смещение от начала объекта float data = texelFetch(obj_data, ofs + ofs2); }

anonymous ()
Ответ на: GPGPU от anonymous

Я постом выше это уже предложил.

Пока все времени нет это реализовавать, блин.

И мне кажется что буфер все-таки лучше чем одномерная текстура т.к. он может быть много больше размером. Или исхитриться и адресовать блоки в двумерной текстуре?

timdorohin ★★★ ()