Vulkan Массив констант специализации

Можно ли иметь массив констант специализации, чтобы код glsl выглядел примерно так:

layout(constant_id = 0) const vec2 arr[2] = vec2[] (
    vec2(2.0f, 2.0f),
    vec2(4.0f, 4.0f)
);

или, альтернативно:

layout(constant_id = 0) const float arr[4] = float[] (
    2.0f, 2.0f,
    4.0f, 4.0f
);

Насколько я читал, нет ограничений на количество констант специализации, которые можно использовать, поэтому кажется странным, что это было бы невозможно, но когда я пытаюсь сделать это выше, компилятор SPIR-V уведомляет меня, что «constant_id» может только применяться к скаляру. В настоящее время я использую универсальный буфер для предоставления данных, но я хотел бы исключить резервный буфер и необходимость привязки буфера перед рисованием, а также позволить системе оптимизировать код во время создания конвейера, если это возможно.


person Ryoku    schedule 02.03.2021    source источник
comment
Если это действительно неизменные константы времени компиляции, то в худшем случае вы можете прочитать SPIR-V, найти интересующий массив и просто манипулировать значениями на месте, прежде чем передавать их Vulkan.   -  person Nicol Bolas    schedule 02.03.2021
comment
@NicolBolas Данные меняются нечасто и только тогда, когда конвейер все равно необходимо реконструировать. Просто чтобы убедиться, что я понимаю, что вы предлагаете, вы думаете, что я должен отсканировать SIR-V в формате массива символов после того, как он был прочитан из файла, и заменить массив вручную. Это хорошая идея, если нет очевидного решения, о котором я даже не думал.   -  person Ryoku    schedule 02.03.2021
comment
просканируйте SIR-V в формате массива символов массива слов. SPIR-V определяется как массив 32-разрядных слова. Но да, это общая идея.   -  person Nicol Bolas    schedule 02.03.2021


Ответы (1)


В то время как GLSL с привкусом Vulkan требует, чтобы константы специализации были скалярами, SPIR-V сам по себе не является столь ограничивающим. Вы можете объявить массив констант специализации точно так же, как вы можете объявить неспециализированный массив констант. Последний фактически становится первым при предоставлении констант специализации. Интерфейс для специализации констант в Vulkan признает возможность того, что разные специализированные константы имеют разные размеры, поэтому их массив будет допустимым с точки зрения API.

Но пока вы привязаны к GLSL, вам приходится жить в рамках его ограничений. По крайней мере, что касается поколения SPIR-V.

Однако, если вы хотите сделать некоторые операции на SPIR-V после его создания, вы можете построить то, что вам нужно. Зная имя рассматриваемого массива, вы можете отследить OpName, который соответствует этому имени массива. Как только вы его найдете, вы сможете найти ResultID (каждый код операции SPIR-V имеет такой), который указывает код операции OpName. Этот код операции должен быть OpConstantComposite.

Все, что вам нужно сделать, это превратить этот опкод OpConstantComposite в OpSpecConstantComposite. Два кода используют одни и те же параметры и так далее, поэтому вы просто заменяете код операции другим.

person Nicol Bolas    schedule 02.03.2021
comment
Хорошо, я понимаю, что ты говоришь. К сожалению, glsl еще не имеет каких-либо расширений, которые можно было бы включить для него, чтобы разрешить специфические функции Vulkan, подобные этой, но, по крайней мере, спецификация Vulkan позволяет это в первую очередь. Поскольку кажется, что мне придется анализировать сами двоичные данные, возможно, вы знаете какие-либо ресурсы для изучения языка или спецификация является лучшим вариантом? - person Ryoku; 02.03.2021
comment
@Ryoku: Спецификация SPIR-V довольно читабельна; это не похоже на разбор текста. Язык спроектирован таким образом, чтобы его можно было легко анализировать, а коды операций определяют, сколько параметров они принимают как часть языка. Это делает повторение SPIR-V для поиска определенных определений или идентификаторов результатов довольно простым. И я совершенно уверен, что есть инструменты, которые могут позаботиться о большей части работы за вас. - person Nicol Bolas; 02.03.2021
comment
@Ryoku: я изменил свой ответ, указав лучший способ справиться с этим. - person Nicol Bolas; 02.03.2021
comment
Хорошо, кажется, я понял, я думаю, что мне придется разработать свой собственный инструмент для автоматизации процесса, чтобы мне не приходилось вручную редактировать файл после каждого изменения в gsll. Если я правильно понимаю, я должен использовать обычный const vec2 arr[2] при компиляции SPIR-V. Затем OpName представляет собой символьную строку с нулевым завершением, найденную в разделе отладочной информации. ResultID, прикрепленный к OpName, — это то, что на самом деле использует скомпилированный код. Затем вы можете заменить первый экземпляр, который соответствует ResultID (должна быть инструкция с OpConstantComposite opcode на OpSpecConstantComposite - person Ryoku; 02.03.2021
comment
@Ryoku Это общая идея. - person Nicol Bolas; 02.03.2021
comment
Разве это не должно считаться ошибкой в ​​GLSL? - person Krupip; 03.03.2021
comment
@whn: Что делает это ошибкой в ​​​​языке? GLSL не предназначен для сопоставления с набором функций SPIR-V, поэтому отказ от этого не является ошибкой. - person Nicol Bolas; 04.03.2021
comment
Если синтаксический анализ двоичного формата раздражает и вы предпочитаете текст, вы можете использовать spirv-dis, чтобы разобрать SPIR-V на удобочитаемую сборку, выполнить замену строки, а затем выполнить spirv-as. - person Andrea; 06.03.2021