LINUX.ORG.RU

Осваиваемся с Vulkan

 , , , ,


6

6

Примерно за пол-года вроде как разобрался с Vulkan.

Пишу сейчас рендерер плагин для своего графического движка

https://gitlab.com/KawaiiGraphics/KurisuRenderer

После OpenGL, для которого всё есть GLint либо GLuint, очень порадовала типизация. Также командные буферы – действительно крутая вещь – в них мало того, что можно писать из нескольких потоков (хотя и с ограничениями), так ещё и записанные однажды, они могут использоваться многократно! Возможность обеспечить более полную загрузку железа с меньшим временем на ожидание вертикальной синхронизации, например, через явное управление очередями тоже впечатляет.

В общем Vulkan в целом мне зашёл. Но есть несколько «но».

Во-первых непонятно зачем перекорёжили гомогенные координаты – ось y зачем-то направили вниз, а глубину и вовсе загнали в интервал от 0 до 1, вместо -1 до 1. Насколько я понимаю, то как направлены оси, в общем-то, ни от чего не зависит. Просто решили, что они направлены вот так и всё. А потому не ясно зачем было менять их – если бы оси были направлены как в OpenGL, можно было бы кормить Vulkan теми же матрицами и мешами, что и OpenGL без всяких плясок с бубном в шейдерах. Ну да ладно, направили оси иначе и направили.

Во-вторых и в главных – SPIRV. В OpenGL замечательная система шейдерных модулей, для которых компиляция отделена от линковки, которая позволяет приложению конструировать шейдерные программы (а в последних версиях OpenGL стадии) из функциональных взаимозаменяемых блоков. Совершенно не ясно, зачем было её херить :( В Vulkan стадии стали неделимыми, так ещё и бинарными. У нас всё ещё графический API и ли какой-нибудь уродский .NET с промежуточным байт кодом? Видимо разработчикам движков так ненавязчиво предлагается иметь некоторый набор заданных заранее семейств материалов и не давать пользователям в руки шейдеры в принципе? Но это же дно-о-о. Мы так в 90-е – 00-е вернёмся, когда был только фиксированный графический конвейер – и всё. В 20-х у нас будет чуть больше моделей освещения/затенения, парочка интересных эффектов водной поверхности, огня и т.д. Но всё так же никакой гибкости.

В общем будущее светло, но не безоблачно. Многопоточный рендеринг, кеширование сцен и возможность безбубенной многооконности, сияют, превращая ночь в день, а днём затмевая Солнце; а маячащая на горизонте возможность multi GPU через DMABUF звучит как гимн разума и изобретательности :D Но отношение Khronos к шейдерам, как минимум, настораживает..

Кто уже тоже успел повулканить? Что думаете о наступившем будущем?

★★★★★

Последнее исправление: robus (всего исправлений: 1)

В линуксе мало игр. В геймдеве мало линуксоидов…

А ты этим for fun занимаешься, или по работе?

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

В линуксе мало игр

Ну, это лучше, чем если бы было как на Android – куча всякого шлака без задумки, без сюжета, без графония..

В геймдеве мало линуксоидов

В этой стране в принципе геймдев не существует как индустрия. На заокраинном мне видится ситуация так – линуксоидов очень небольшая часть из всех ПК-юзеров; из разработчиков линуксоидов значительно больше (в %), но всё ещё мало. В геймдеве – больше, чем среди в всех пользователей, но меньше, чем среди всех разработчиков.

for fun

this

robus ★★★★★
() автор топика

Во-вторых и в главных – SPIRV.

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

V1KT0P ★★
()

Во-первых непонятно зачем перекорёжили гомогенные координаты – ось y зачем-то направили вниз, а глубину и вовсе загнали в интервал от 0 до 1, вместо -1 до 1. Насколько я понимаю, то как направлены оси, в общем-то, ни от чего не зависит. Просто решили, что они направлены вот так и всё. А потому не ясно зачем было менять их – если бы оси были направлены как в OpenGL, можно было бы кормить Vulkan теми же матрицами и мешами, что и OpenGL без всяких плясок с бубном в шейдерах. Ну да ладно, направили оси иначе и направили.

  1. Ой, да какая нахрен разница, смапил/настроил и забыл

  2. Для прямоХ эти оси тоже другие, так что всё ок, всё везде разное :)

Во-вторых и в главных – SPIRV. В OpenGL замечательная система шейдерных модулей, для которых компиляция отделена от линковки, которая позволяет приложению конструировать шейдерные программы (а в последних версиях OpenGL стадии) из функциональных взаимозаменяемых блоков. Совершенно не ясно, зачем было её херить :( В Vulkan стадии стали неделимыми, так ещё и бинарными. У нас всё ещё графический API и ли какой-нибудь уродский .NET с промежуточным байт кодом? Видимо разработчикам движков так ненавязчиво предлагается иметь некоторый набор заданных заранее семейств материалов и не давать пользователям в руки шейдеры в принципе? Но это же дно-о-о. Мы так в 90-е – 00-е вернёмся, когда был только фиксированный графический конвейер – и всё. В 20-х у нас будет чуть больше моделей освещения/затенения, парочка интересных эффектов водной поверхности, огня и т.д. Но всё так же никакой гибкости.

Ты наркоман или старообрядник?

  1. Стадии компиляции/линковки разнесены. Компиляция – шейдерные модули; линковка – пайплайн.

  2. Бинарники – добро. Парсинг текста в движке – кусок говна, который я никогда не понимал в опенгл.

а маячащая на горизонте возможность multi GPU

Уже вполне работает как и с DeviceGroup так и с внешними файл дескрипторами.

Но отношение Khronos к шейдерам, как минимум, настораживает..

Серьёзно, в вулкане шейдеры пофиксили, а не сломали.

Кто уже тоже успел повулканить? Что думаете о наступившем будущем?

По сравнению с GNM – переусложненное запутанное говно. По сравнению со всем остальным – восторг.

// Добро пожаловать :)

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

но почему SPIRV вдруг плохой?

Потому, что в нём шейдерные стадии неделимы – «снаружи» Vulkan-а оказалась не только компиляция шейдеров, что было бы ещё терпимо, но и линковка тоже. С программой теперь предполагается поставлять не шейдерные модули, а целиком слинкованные и «скомпиленные» (в промежуточный байт код, который опять потом компилить надо ЛОЛ) стадии (вершинная стадия, геометрическая, фрагментная..).

А уж если у нас в программе / движке есть какая то процедурная генерация шейдеров – то совсем труба! В OpenGL можно иметь «динамические» шейдерные модули которые генерируются программой, а остальные просто загружены из файла и скомпилены один раз; таким при изменении модуля происходит перекомпиляция этого модуля и перелинковка шейдерной программы / стадии. В Vulkan же надо рекомпилить целиком стадию.

Также на OpenGL можно сделать API для GLSL шейдеров: поставлять с движком шейдерные модули и описание их публичного интерфейса в некой форме. Модули из API будет скомпилированы не более 1 раза (при их первом использовании). В glslang (а именно через это место у Vulkan поддерживается glsl) распарсенный шейдерный модуль может быть задействован не более, чем в 1 программе, копироваться не умеет – аллес; приходится парсить реализацию модуля столько раз, в скольких программах он используется.

В целом получается главный юзкейс, на который Khronos ориентировались – это когда шейдеры являются частью графического движка а для клиентского кода, есть только фиксированный конвеер. Прямо как в старые не добрые времена OpenGL 1.x. Только теперь конвеер зашит не в OpenGL, а в движке. Я же хочу дать пользователю шейдеры, из которых он сможет брать из движка данные и звать его API, когда нужно (модели освещения, вершины, нормали и проч.). Движок Kawaii3D ожидает от клиентского кода шейдеры в слегка модифицированном GLSL, рендерер плагины (на данный момент существуют MisakaRenderer и KurisuRenderer) достаточно легко получают из него чистый GLSL и работают уже с ним.

Не говоря уже о том, что это просто архитектурно уродливое решение. В OpenGL есть язык шейдеров, а в Vulkan – адово х**дрыгало с промежуточным байт кодом и кучей фронтендов не ясно на кой чёрт существующих, напоминающее до кучи .NET.

зоопарк шейдерных языков GLSL/Cg/HLSL компилировался в этот SPIRV

В OpenGL есть только GLSL. Зоопарка там нет. Не зачем его создавать. Дожили до того, что на расте шейдеры писать хотят.

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

Уже вполне работает как и с DeviceGroup так и с внешними файл дескрипторами.

В Vulkan работает, я в курсе. Я про поддержку этого добра в своём проекте (там пока только через DeviceGroup).

По сравнению с GNM – переусложненное запутанное говно

Что есть GNM?

Ты наркоман или старообрядник?

Я клиентскому коду возможность шейдеров вручил.

robus ★★★★★
() автор топика
Последнее исправление: robus (всего исправлений: 1)
Ответ на: комментарий от robus

> В OpenGL есть только GLSL

Извините что вмешиваюсь в разговор серьёзных людей. Я просто поправлю, что, помимо языка GLSL, существует возможность писать шейдеры на ассемблере ARB assembly language (расширения vertex_program, fragment_program). https://ru.wikipedia.org/wiki/OpenGL#OpenGL_2.0 В Wine 5.0 даже добавили возможность выбирать, как именно будут транслироваться шейдеры из Direct3D в OpenGL: в GLSL или arb (vertex/fragment) (пруф в последнем пункте про Direct3D в новости про Wine 5.0)

ZenitharChampion ★★★★★
()
Последнее исправление: ZenitharChampion (всего исправлений: 4)
Ответ на: комментарий от robus

Что есть GNM?

Прориетарная апишка, с которой можно работать на всех уровнях абтракции начиная с «дх11 стайл – пишем код не приходя в сознание» и заканчивая ручным заполнением регистров видяшки. Где-то в середине, когда ты ставишь барьеры и кеш-флаши руками наступает дзен)

Я клиентскому коду возможность шейдеров вручил.

Клиентскому коду не нужны шейдеры. Клиентскому коду нужны материалы и модели, для которых отдельные тулзы есть. Задача движка – обрабатывать гейм-логику и быстро работать, эдитор – другая задача

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

Клиентскому коду нужны материалы и модели

Предлагается делать очередной двиг с безальтернативным PBR и гибкостью примерно как у полуторного OpenGL? Или я неправильно понял и есть некие стандарты (хотя бы даже де-факто) описания материалов, в которых [псевдо-]шейдеры, а не просто наборы параметров? Если так, то хотелось бы знать, где можно почитать про это.

Задача движка – обрабатывать гейм-логику и быстро работать

Это игровой движок. Там по мимо графического движка ещё скрипты, звук, обработка ввода, сеть и много всего. Я, кст, не спеша пишу KawaiiWorlds на основе своего Kawaii3D. И это уже будет игровой движок.

robus ★★★★★
() автор топика
Последнее исправление: robus (всего исправлений: 1)
Ответ на: комментарий от ZenitharChampion

Я просто поправлю, что, помимо языка GLSL, существует возможность разрабатывать спецэффекты на языках ассемблера (расширения vertex_program, fragment_program)

Речь про vertex_program и fragment_program? Это не та ли древняя технология, на смену которой пришёл GLSL? Извиняюсь, не очень хорошо знаю историю..

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

Потому, что в нём шейдерные стадии неделимы – «снаружи» Vulkan-а оказалась не только компиляция шейдеров, что было бы ещё терпимо, но и линковка тоже. С программой теперь предполагается поставлять не шейдерные модули, а целиком слинкованные и «скомпиленные» (в промежуточный байт код, который опять потом компилить надо ЛОЛ) стадии (вершинная стадия, геометрическая, фрагментная..).

А как же тогда работают трансляторы типа DXVK и MoltenGL?

annulen ★★★★★
()

глубину и вовсе загнали в интервал от 0 до 1, вместо -1 до 1

Исправили древнюю ошибку OpenGL. Знаете как устроены числа с плавающей точкой? Между 0 и 0.5 намного больше представимых чисел, чем между 0.5 и 1. То есть точность z-буфера максимальна вблизи z=0. В OpenGL этот 0 болтается где-то среднем плане, где такая точность не нужна.

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

Он поверх metal, вроде как

Упс. Мне казалось что реализацию opengl поверх вулкана тоже кто-то делал

Самостоятельно компилит dxbc и dxso шейдеры.

В смысле в нем свой собственный компилятор, или он все-таки как-то использует компилятор от видеодрайвера?

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

В смысле в нем свой собственный компилятор или он все-таки как-то использует компилятор от видеодрайвера?

Собственный компилятор для dxbc и для dxso.

Полученный SPIRV код уже непрозрачно для программиста компилируется драйвером (реализацией vulkan) в машинный код устройства.

Упс. Мне казалось что реализацию opengl поверх вулкана тоже кто-то делал

Да, есть такой проект. Zink Gallium Driver. Вот как он работает, вообще ХЗ :D

robus ★★★★★
() автор топика

Эх когда куплю поддерживающую эту Джамалунгму видеокарту, тоже начну пердолиться. Тоесть если я правильно понимаю, вот сейчас у меня на GL есть материал к которому можно просто приложить фрагментный и вершинный шейдера которые движок просто подхватит и слинкует и исполнит. А для поиска нужного эффекта можно играться прямо в live режиме просто пересобирая 1 маленький шейдерок для 1 маленького эффекта не трогаая тонну остальных. Правильно ли я понимаю что если я хочу внести изменения я должен буду погасить вулкан приложение, пересобрать все шейдеры и только потом увижу результат перезапустив мир по сути?

LINUX-ORG-RU ★★★★★
()
Последнее исправление: LINUX-ORG-RU (всего исправлений: 1)
Ответ на: комментарий от LINUX-ORG-RU

Тоесть если я правильно понимаю, вот сейчас у меня на GL есть материал к которому можно просто приложить фрагментный и вершинный шейдера которые движок просто подхватит и слинкует и исполнит. А для поиска нужного эффекта можно играться прямо в live режиме просто пересобирая 1 маленький шейдерок для 1 маленького эффекта не трогаая тонну остальных

Да, примерно так я планирую сделать в KawaiiWorlds.

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

Не обязательно. Приложение само может компилить твой шейдер в SPIRV. Мой Vulkan рендерер зависит в рантайме от glslang ради этого. Разница в том, что Vulkan приложение должно будет перекомпилить целиком стадию (внёс изменения, например, в вершинный шейдер – все вершинные шейдеры этого материала (точнее пайплайна) нужно будет пересобрать), что значительно сильнее ударит производительность. Если шейдеры меняет человек в live режиме в каком-нибудь редакторе, это нормально. Там можно хоть на целую секунду подвиснуть. Если же шейдер меняется программой, как реакция на некое событие, то жопь.

robus ★★★★★
() автор топика

Про графический движок Kawaii3D стоит сказать, что он не содержит коллекции семейств материалов. Взамен он принимает от клиентского кода шейдерные программы на наречии GLSL. Renderer plugins получают из ядра движка информацию о зависимостях шейдерных модулей и код на чистом glsl и имеют с этим дело. Также ядро движка ничего не рендерит, не загружает и т.д. – всем этим заняты плагины.

robus ★★★★★
() автор топика

Во-вторых и в главных – SPIRV. В OpenGL замечательная система шейдерных модулей, для которых компиляция отделена от линковки, которая позволяет приложению конструировать шейдерные программы (а в последних версиях OpenGL стадии) из функциональных взаимозаменяемых блоков. Совершенно не ясно, зачем было её херить :( В Vulkan стадии стали неделимыми, так ещё и бинарными.

Entry point-ов может быть несколько, плюс шейдерный модуль может иметь несколько конфигураций с параметризованной компиляцией. А всё потому, что программы обычно маленькие, а памяти обычно много - есть смысл обменивать компактность программы на производительность. По этой причине современные либы для вычислений на видюхах имеют такой безумный размер. Вон, cuDNN 400 Мб весит.

У нас всё ещё графический API и ли какой-нибудь уродский .NET с промежуточным байт кодом?

Большая часть компилирования - это парсинг. Даже питон, тормознутый медленный питон компилирует исходники, потому что даже для него парсить исходники - это слишком долго.

Видимо разработчикам движков так ненавязчиво предлагается иметь некоторый набор заданных заранее семейств материалов и не давать пользователям в руки шейдеры в принципе?

Ты перекомпилируешь проект при внесении изменений в исходники? Чем шейдеры должны отличаться?

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

По сравнению с GNM – переусложненное запутанное говно. По сравнению со всем остальным – восторг

Комитеты по другому не умеют.

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

В OpenGL можно иметь «динамические» шейдерные модули которые генерируются программой, а остальные просто загружены из файла и скомпилены один раз; таким при изменении модуля происходит перекомпиляция этого модуля и перелинковка шейдерной программы / стадии. В Vulkan же надо рекомпилить целиком стадию

https://github.com/google/shaderc

А так - мало кому нужно делать прям вообще динамические шейдерные модули. Обычно алгоритм все-таки статичен с минимальной параметризацией.

byko3y ★★★★
()

Во-первых непонятно зачем перекорёжили гомогенные координаты – ось y зачем-то направили вниз

Я бы вообще и горизонтальную ось изменил справа-налево. Чтобы разработчик понимал, что выбранная система координат 3D-пространства никак не связана с системой координат проекции камеры. И мапить одно в другое нужно всегда в том или ином виде. Шутка конечно про справа-налево, но думаю смысл понятен.

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

В Vulkan точно так же, скомпилированные модули в SPIR-V, линковка в пайплайне, комбинировать модули друг с другом после компиляции как угодно.

Приложение само может компилить твой шейдер в SPIRV. Мой Vulkan рендерер зависит в рантайме от glslang ради этого.

Ты так говоришь, будто это что-то плохое. Ты же смирился с идеологией вулкана, что клиентская часть переезжает из драйвера в твой код, раздувая его, но позволяя большую гибкость. Компиляция шейдеров чётко следует этой линии партии.

Разница в том, что Vulkan приложение должно будет перекомпилить целиком стадию (внёс изменения, например, в вершинный шейдер – все вершинные шейдеры этого материала (точнее пайплайна) нужно будет пересобрать), что значительно сильнее ударит производительность. Если шейдеры меняет человек в live режиме в каком-нибудь редакторе, это нормально. Там можно хоть на целую секунду подвиснуть. Если же шейдер меняется программой, как реакция на некое событие, то жопь.

Всё с разницей до наоборот. В OpenGL действительно будет жопь, потому что перекомпиляция шейдера обязана быть встроена в поток графики, добавляя неконтролируемую задержку. В Vulkan компиляцию можно разнести по потокам, компилировать в фоне, кешировать результаты, сделать процесс контролируемым.

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

Там можно хоть на целую секунду подвиснуть.

Но почему-то те же IDE прекрасно работают с подсветкой синтаксиса и даже тяжелющими компиляторами C++ кода в реальном времени без подвисаний. Всё из-за добавления промежуточной стадии между пользовательским вводом и откликом парсера, когда новых данных от последнего ещё нет, но редактор продолжает нормально работать.

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

Я бы вообще и горизонтальную ось изменил справа-налево

Да хоть по диагонали! Хоть экранные координаты вместо гомогенных туда засунуть можно. Просто когда можно в шейдере на каждую вершину выполнять на 1 матричное умножение меньше, за счёт того, что матрица view_projection matrix на хосте расчитан, то хочется этим воспользоваться. В этом суть оптимизации.

скомпилированные модули в SPIR-V, линковка в пайплайне

Нет.

The stage member of each element of pStages must be unique

Таким образом, моменту создания пайплайна каждая стадия должна уже быть слинкована.

Всё с разницей до наоборот. В OpenGL действительно будет жопь, потому что перекомпиляция шейдера обязана быть встроена в поток графики, добавляя неконтролируемую задержку. В Vulkan компиляцию можно разнести по потокам, компилировать в фоне, кешировать результаты, сделать процесс контролируемым.

Ну как бы не придерёшься – действительно, можно разнести по разным потокам компиляцию шейдеров :D Вот только самой компиляции стало больше, по сравнению с OpenGL, где можно было рекомпильнуть один маленький модуль, а тут целиком стадию , да и многопоточность в данном случае не значит асинхронность. Пока шейдеры не скомпилились, этот пайплайн использовать нельзя – не будешь же рендерить мусор.

Но почему-то те же IDE прекрасно работают с подсветкой синтаксиса и даже тяжелющими компиляторами C++ кода в реальном времени без подвисаний.

Вы когда IDE последний раз видели? У меня Qt Creator после запуска целую вечность (около 15 секунд – 15000000 микросекунд) работает в режиме блокнота – код не раскрашен, автодоп не работает, навигации по коду нет. Мне норм подождать 15 секунд, пока сессия в Qt Creator прогрузится, но в графическом движке поиметь фреймтайм в 15000000 почти равносильно катастрофе.

robus ★★★★★
() автор топика
Последнее исправление: robus (всего исправлений: 1)
Ответ на: комментарий от byko3y

Entry point-ов может быть несколько

Но шейдерный модуль – только 1 на стадию.

шейдерный модуль может иметь несколько конфигураций с параметризованной компиляцией

Константы специализации? Они же именно что константы, да ещё и строго скалярные. Подходят для динамических массивов (не то чтобы для этого SSBO не подходили, ЛОЛ), для метапрограммирования (даже такого зачаточного, как у меня в движке уже есть) – нет.

Ты перекомпилируешь проект при внесении изменений в исходники? Чем шейдеры должны отличаться?

Ты перекомпилируешь игру при изменении скриптов? Чем шейдеры должны отличаться?

Большая часть компилирования - это парсинг. Даже питон, тормознутый медленный питон компилирует исходники, потому что даже для него парсить исходники - это слишком долго.

Эмм.. OpenGL как бы тоже компилирует шейдеры, а не интерпретирует их. Просто делает это эффективнее, чем glslang.

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

А как этот shaderc уговорить линковать несколько модулей в одну стадию? Уж лучше glslang, тот, пусть и неэффективно, но умеет в линковку.

А так - мало кому нужно делать прям вообще динамические шейдерные модули. Обычно алгоритм все-таки статичен с минимальной параметризацией.

не давать пользователям в руки шейдеры в принципе? Но это же дно-о-о. Мы так в 90-е – 00-е вернёмся, когда был только фиксированный графический конвейер – и всё. В 20-х у нас будет чуть больше моделей освещения/затенения, парочка интересных эффектов водной поверхности, огня и т.д. Но всё так же никакой гибкости.

robus ★★★★★
() автор топика
Ответ на: комментарий от LINUX-ORG-RU

когда куплю поддерживающую эту Джамалунгму видеокарту, тоже начну пердолиться

NVIDIA поддерживает начиная с Kepler, AMD с GCN 1.0, Intel с Ivy Bridge. Это что же за видюха такая, которая не поддерживает; как на такой играть – да чёрт с ним, с «играть», как на такой видео смотреть 0_0

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

Клиентскому коду не нужны шейдеры.

а мужики то не знали. Нужны они, ну и клиентский код надо в опенсорс загонять

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

Нет.

The stage member of each element of pStages must be unique

Не нет, а да (-: Речь идёт про поле VkShaderStageFlagBits, которое обязано быть уникальным, то-есть при линковке нельзя, к примеру, использовать одновременно два фрагментных шейдера VK_SHADER_STAGE_FRAGMENT_BIT.

При этом сами модули (VkShaderModule) могут быть загружены один раз и многократно использоваться в разных пайплайнах.

Вы когда IDE последний раз видели? У меня Qt Creator после запуска целую вечность (около 15 секунд – 15000000 микросекунд) работает в режиме блокнота – код не раскрашен, автодоп не работает, навигации по коду нет.

QtCreator — мой ежедневный рабочий инструмент. Я подобный пример и имел в виду и твой ответ только его подтверждает. Чудес не бывает, если парсеру синтаксиса нужно 15 секунд, то их так или иначе прийдётся дождаться. Вопрос только какое должно быть поведение редактора в это время. Если заблокировать UI не вариант, то нужно дать возможность навигации и редактирования неподсвеченного текста, что тот же QtCreator и делает.

Поведение конечно же будет меняться от программы к программе. В играх, к примеру, часто делают подгрузку потенциально скоро используемых ресурсов в фоне. Но если игра не угадала или не успела подгрузить, то могут временно показывать пустые локации, заглушки шейдеров, размытые текстуры с большим mip-level, и так далее. Если это не вариант, игра может в крайнем случае временно заблокироваться с плашкой «Loading…».

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

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

Просто когда можно в шейдере на каждую вершину выполнять на 1 матричное умножение меньше, за счёт того, что матрица view_projection matrix на хосте расчитан, то хочется этим воспользоваться. В этом суть оптимизации.

Не вижу противоречий. Если матрица проекций не меняется и может быть посчитана на хосте, то ты её и считаешь один раз с учётом той или иной системы координат камеры. Направления осей ничего не меняет с точки зрения оптимизации.

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

Radeon HD 6850. 80+ игр в стиме. SOMA,CSGO,Valley,L4D2 , etc… Всё на свободном драйвере radeon. 1080p моник, аналогичное ютубчик всё шикарно. Так же как и ты игродевкущупаю https://youtu.be/SXSQFxzjNcs?t=266 но в более скромных масштабах ибо двиг не мой, а форк коранжа на #version 120 ибо всё что выше трешак непереносимый и вообще ой всё :D

LINUX-ORG-RU ★★★★★
()
Последнее исправление: LINUX-ORG-RU (всего исправлений: 1)
Ответ на: комментарий от robus

Ты перекомпилируешь игру при изменении скриптов? Чем шейдеры должны отличаться?

WC3, SC2, Unreal engine свои скрипты компилируют, если чо. Потому что производительность. И перекомпиляция скриптов не ведет к перекомпиляции всего движка. Вот если бы ты сказал «шейдеры 10 минут перекомпилируются, так невозможно работать», то я бы сказал «да, это никуда не годится, нужно срочно что-то с этим делать».

OpenGL как бы тоже компилирует шейдеры, а не интерпретирует их. Просто делает это эффективнее, чем glslang

Он их перекомпилирует по необходимости. Или все-таки есть инфа, что opengl таки какой-то магией делает трансляцию эффективнее?

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

А как этот shaderc уговорить линковать несколько модулей в одну стадию? Уж лучше glslang, тот, пусть и неэффективно, но умеет в линковку

Да, в shaderc ребята пока тупят: https://github.com/google/shaderc/issues/315 . Но shaderc так-то подразумевался как упрощенный вариант.

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

В этой стране в принципе геймдев не существует как индустрия.

Ржал яки конь. Если ты не знаешь геймдевных компаний отечественных, то это вовсе не значит, что их нет.

alex-w ★★★★★
()

дерзай!

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

Потому что производительность Вот если бы ты сказал «шейдеры 10 минут перекомпилируются, так невозможно работать», то я бы сказал «да, это никуда не годится, нужно срочно что-то с этим делать».

Он их перекомпилирует по необходимости. Или все-таки есть инфа, что opengl таки какой-то магией делает трансляцию эффективнее?

Во-первых – он перекомпилирует только тот модуль, который был изменён, а не целиком всю стадию.

Во-вторых он имеет возможность компилировать сразу в машинный код видеокарты, а не в промежуточный байт код, который потом опять компилировать нужно. Нужно меньше вычислений для того чтобы переделать glsl в машинный код, чем чтобы переделать glsl в SPIRV, а потом его в машинный код.

Если даже настолько простые технологические решения, как раздельная компиляция, для вас магия, то я даже и не знаю что сказать.

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

Если матрица проекций не меняется и может быть посчитана на хосте, то ты её и считаешь один раз с учётом той или иной системы координат камеры. Направления осей ничего не меняет с точки зрения оптимизации.

Не меняют. Просто теперь движок должен учитывать, что экранные координаты бывают не только такие, как в OpenGL. Никакой катастрофы тут нет, просто небольшое усложнение кода.

robus ★★★★★
() автор топика
Ответ на: комментарий от alex-w

Но окромя индюшатины, аля бехолдер ничего в РФ не выпускают из игр. Никаких тебе колофдьюти, дотанов, вовок, ксок и даже танки не в РФ клепают.

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

А проверяется легко - покажите мне отечественный игровой движок хоть 1 серьёзного уровня. Пускай даже уровня опенсорсного огра.

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

Во-вторых он имеет возможность компилировать сразу в машинный код видеокарты, а не в промежуточный байт код, который потом опять компилировать нужно. Нужно меньше вычислений для того чтобы переделать glsl в машинный код, чем чтобы переделать glsl в SPIRV, а потом его в машинный код.

Несовсем верно, GLSL - это шейдер в текстовом представлении, SPIRV - это тот-же шейдер в бинарном представлении.
В случае с GLSL надо парсить текст шейдера, что хоть и делается быстро но все-равно тратятся ресурсы впустую. Плюс сам парсинг текстового представление еще то удовольствие(тут я вспоминаю как Intel в ранней реализации парсера OpenCL для одного из вариантов инициализации интерпретировал стандарт по своему, что ломало код).

SPIRV - это уже распарсенный текст шейдера в бинарном представлении, что позволяет быстро его верифицировать и скомпилировать.

То что называется компиляция в SPIRV это не обязательно означает прохождение таких-же стадий что и при компиляции в машинный код. Например можно написать компилятор Python/Ruby кода в GLSL текстовое представление, станет ли GLSL от этого хуже? При компиляции в SPIRV происходят алгоритмические оптимизации, которые актуальны для любой архитектуры и которые можно сделать единожды вместо-того чтоб надеяться что компилятор драйвера сделает именно эту оптимизацию.

Сам подумай что проще для разработчиков GPU писать кучу компиляторов GLSL/HLSL/Cg/etc. и поддерживать разные версии или всего один компилятор который компилирует SPIRV?
Аналогично для разработчиков игр, им приходится под Linux один язык использовать, под Windows другой. Это нихрена не удобно. В итоге все-равно все сводится к тому что создали/создадут компилятор условно «универсального шейдерного языка» или С/C++/etc. в GLSL/HLSL/Cg/etc.
Плюс надо учитывать что пользователи не часто обновляют драйвера и если у пользователя старые драйвера в котором у GLSL/HLSL/Cg/etc. компилятора еще нет какой-то оптимизации то разработчикам игры ничего не остается кроме как показать сообщение игроку про необходимость обновления драйвера. А что если оптимизации вообще не завезли? А никаким изменением исходного кода добиться этой оптимизации невозможно так как нет низкоуровневого доступа, именно такого какой дает SPIRV.
С помощью SPIRV разработчик может оптимизировать представление с помощью новых оптимизаций которые вот только вчера придумали так чтоб оно скомпилировалось в машинный код драйвером в максимально эффективный код в независимости от того насколько древний драйвер и насколько древний компилятор там.

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

Не нет, а да (-: Речь идёт про поле VkShaderStageFlagBits, которое обязано быть уникальным, то-есть при линковке нельзя, к примеру, использовать одновременно два фрагментных шейдера VK_SHADER_STAGE_FRAGMENT_BIT. При этом сами модули (VkShaderModule) могут быть загружены один раз и многократно использоваться в разных пайплайнах.

к примеру, использовать одновременно два фрагментных шейдера

Это и есть линковка. Когда в одном шейдере у нас, например

#version 450 core
#extension GL_ARB_bindless_texture: require

layout(bindless_sampler) uniform;

layout(std140, binding = 1) uniform Material
{
    vec4 bg;
} material;

layout(std140, binding = 2) uniform Model {
    sampler2D tex;
} model;

layout(std140, binding = 3) uniform globalUboTest
{
    vec2 texCoordCenter;
} test;

vec4 getTexel(in vec2 texCoord)
{
    if(test.texCoordCenter != vec2(0.5, 0.5))
        return vec4(0.75, 0.5, 0.5, 1.0);

    float k = 1.0 - distance(texCoord, vec2(0.5, 0.5));

    vec4 texelColor = texture(tex, texCoord);

    return vec4(k * mix(material.bg.rgb, texelColor.rgb, texelColor.a), 1.0);
}

А в другом

#version 450 core

layout(location = 1) in highp vec3 pos;
layout(location = 0) out highp vec4 color;

vec4 getTexel(in vec2 texCoord);

void main(void)
{
    color = getTexel(pos.xy);
}

И они линкуются в единую стадию.

При этом сами модули (VkShaderModule) могут быть загружены один раз и многократно использоваться в разных пайплайнах.

А то, что стадии независимы, так это совсем другое.

Если нужно перекомпилить шейдер на лету, то хоть ты тресни, на это нужно потратить время

Да ладно :D Скажем в нашем примере поменяется только второй шейдер. Станет

#version 450 core

layout(location = 1) in highp vec3 pos;
layout(location = 0) out highp vec4 color;

vec4 getTexel(in vec2 texCoord);

void main(void)
{
    color = vec4(vec3(1.0) - getTexel(pos.xy).rgb, 1.0);
}

Тогда, в OpenGL мы только его и перекомпилим и слинкуем программу заново. В glslang придётся перекомпиливать всю стадию – т.е. помимо изменившегося модуля ещё и реализацию getTextel.

В OpenGL эта задача никак не решалась, компиляторы GLSL, как правило, встроены прямо в драйвер и точно так же кушают процессорное время

Кушают его меньше, так как выполняют меньше работы.

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

Простой перенос может и улучшит. Вот только glslang это не компилятор шейдеров, перенесённый из драйвера. Это кривоватая его замена, заглушка в лучшем случае.

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

Тогда, в OpenGL мы только его и перекомпилим и слинкуем программу заново.

Я вот смотрю что написано в спецификации SPIRV 1.0: https://www.khronos.org/registry/spir-v/specs/1.0/SPIRV.html
И там написано что можно вызывать функции из уже скомпилированных модулей, как ты это описал.

Вот здесь написано что можно вызывать функции из других модулей:

2.9. Function Calling

To call a function defined in the current module or a function declared to be imported from another module, use OpFunctionCall with an operand that is the <id> of the OpFunction to call, and the <id>s of the arguments to pass. All arguments are passed by value into the called function. This includes pointers, through which a callee object could be modified.

А вот тут написано что можно импортировать функции которые экспортированы другим модулем и что это связывание происходит на этапе линковки:

2.13. Linkage

The ability to have partially linked modules and libraries is provided as part of the Linkage capability.

By default, functions and global variables are private to a module and cannot be accessed by other modules. However, a module may be written to export or import functions and global (module scope) variables. Imported functions and global variable definitions are resolved at linkage time. A module is considered to be partially linked if it depends on imported values.
V1KT0P ★★
()
Последнее исправление: V1KT0P (всего исправлений: 1)
Ответ на: комментарий от V1KT0P

GLSL - это шейдер в текстовом представлении, SPIRV - это тот-же шейдер в бинарном представлении

Нет. SPIRV – это именно что промежуточное представление. И у SPIRV есть собственная текстовая форма.

Аналогично для разработчиков игр, им приходится под Linux один язык использовать, под Windows другой. Это нихрена не удобно.

А зачем. OpenGL под Windows тоже есть.

в независимости от того насколько древний драйвер

Нет. Есть оптимизации, которые уместны при компилировании SPIRV в машинный код. Есть также неилюзорная возможность накосячить при компилировании SPIRV в машинный код. ACO/RADV от RADV отличается только компилятором. При этом производительность их отличается. Причём не только на этапе компилирования шейдеров. То же и с AMDVLK и amdgpu-pro

robus ★★★★★
() автор топика
Последнее исправление: robus (всего исправлений: 1)
Ответ на: комментарий от robus

Нет. Есть оптимизации, которые уместны при компилировании SPIRV в машинный код.

Я в том смысле что есть бОльший контроль над оптимизацией при использовании SPIRV, так как он предоставляет больше возможностей. Я не спорю что от компилятора драйвера ничего не зависит, но это лучше чем было. Тут можно взять к примеру IR LLVM представление и clang как фронтенд. И тут clang может провести многие оптимизации которые увеличат конечную эффективность машинного кода.

SPIRV открывает двери новым языкам и абстракциям, теперь буквально можно на любом языке писать шейдеры лишь бы был компилятор в SPIRV. Конечно можно было бы и раньше в те-же GLSL/HLSL/Cg/etc. компилировать, но вот такой-же эффективности уже не было-бы.

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

Предлагается делать очередной двиг с безальтернативным PBR и гибкостью примерно как у полуторного OpenGL? Или я неправильно понял и есть некие стандарты (хотя бы даже де-факто) описания материалов, в которых [псевдо-]шейдеры, а не просто наборы параметров? Если так, то хотелось бы знать, где можно почитать про это.

ЯННП. В нормальных движках (UE4 например) исходник материала – это граф из математичестких нод, параметров (константы, геймплейные параметры (позиция игрока в мире, настройки FOVа), текстуры) и движковых сущностей (время, frame id, whatever), который компилируется в исходники шейдеров, которые потом отдаются компилятору шейдеров. И всё это сшивается в файл материала, с которым уже и работает движок в рантайме. И в рантайме ничего никуда компилировать не нужно. На гибкость тоже никто не жалуется.

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

Ты перекомпилируешь игру при изменении скриптов? Чем шейдеры должны отличаться?

А я перекомпилирую игру при изменении (движковых) шейдеров, например. Потому что биндинги извлекаются на этапе компиляции щейдеров и зашиваются в бинарь. Чтобы сэкономить на рантаймовых завросах «куда присунуть вот эту вот текстуру». В файлы материалов биндинги зашиваются аналогично и настройка ресурсов для рендеринга материалов сводится к простому проходу по for (const auto& i : material.params()) { cb.bind(i.what(), i.where(); }.

Stil ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.