При написании нетривиальных шейдеров (как и при написании любого другого нетривиального кода) люди делают ошибки. [цитата нужна] Однако я не могу просто отладить его, как любой другой код - вы не можете просто присоединить GDB или отладчик Visual Studio в конце концов. Вы даже не можете выполнять отладку printf, потому что нет формы вывода на консоль. Что я обычно делаю, так это визуализирую данные в цвете, но это очень элементарное и любительское решение. Я уверен, что люди придумали лучшие решения.
Так как же я могу отладить шейдер? Есть ли способ пройти через шейдер? Могу ли я посмотреть на выполнение шейдера на определенной вершине / примитиве / фрагменте?
(Этот вопрос конкретно о том, как отлаживать шейдерный код, похожий на то, как можно было бы отлаживать «нормальный» код, а не об отладке таких вещей, как изменения состояния.)
Ответы:
Насколько я знаю, нет инструментов, позволяющих пошагово проходить код в шейдере (также в этом случае вам нужно будет выбрать только пиксель / вершину, которую вы хотите «отладить», выполнение, вероятно, варьироваться в зависимости от этого).
То, что я лично делаю, это очень хакерская «красочная отладка». Так что я сбрасываю кучу динамических веток с
#if DEBUG / #endif
охранниками, которые в основном говорятТаким образом, вы можете «наблюдать» отладочную информацию таким образом. Я обычно делаю разные трюки, такие как прокалывание или смешивание различных «цветовых кодов», чтобы проверить различные более сложные события или небинарные вещи.
В этой «структуре» я также считаю полезным иметь набор фиксированных соглашений для общих случаев, чтобы, если мне не приходилось постоянно возвращаться и проверять, с каким цветом я связан, с каким. Важно иметь хорошую поддержку горячей перезагрузки шейдерного кода, так что вы можете почти интерактивно изменять отслеживаемые данные / события и легко включать / выключать визуализацию отладки.
Если вам нужно отладить что-то, что вы не можете легко отобразить на экране, вы всегда можете сделать то же самое и использовать один инструмент анализатора кадров для проверки ваших результатов. Я перечислил пару из них как ответ на этот другой вопрос.
Конечно, само собой разумеется, что если я не «отлаживаю» пиксельный шейдер или вычислительный шейдер, я передаю эту информацию «debugColor» по всему конвейеру, не интерполируя ее (в GLSL с
flat
ключевым словом)Опять же, это очень глупо и далеко от правильной отладки, но я застрял в том, что не знаю какой-либо правильной альтернативы.
источник
Также есть GLSL-отладчик . Этот отладчик раньше назывался GLSL Devil.
Сам отладчик очень удобен не только для кода GLSL, но и для самого OpenGL. У вас есть возможность переключаться между вызовами отрисовки и прерывать переключатели шейдеров. Он также показывает вам сообщения об ошибках, переданные OpenGL обратно в само приложение.
источник
Поставщики графических процессоров предлагают несколько предложений, таких как AMD CodeXL или отладчик nSight / Linux GFX от NVIDIA, которые позволяют проходить через шейдеры, но привязаны к аппаратному обеспечению соответствующего поставщика.
Позвольте мне заметить, что, хотя они доступны в Linux, у меня всегда был небольшой успех с их использованием там. Я не могу комментировать ситуацию под Windows.
Вариант, который я недавно использовал, заключается в модульном кодировании моего шейдерного кода
#includes
и ограничении включенного кода общим подмножеством GLSL и C ++ & glm .Когда я сталкиваюсь с проблемой, я пытаюсь воспроизвести ее на другом устройстве, чтобы увидеть, является ли проблема той же самой, которая намекает на логическую ошибку (вместо проблемы с драйвером / неопределенного поведения). Существует также вероятность передачи неверных данных в графический процессор (например, с помощью неправильно связанных буферов и т. Д.), Которые я обычно исключаю либо путем отладки вывода, как в ответе cifz, либо путем проверки данных через apitrace .
Когда это логическая ошибка, я пытаюсь восстановить ситуацию с GPU на CPU, вызывая включенный код на CPU с теми же данными. Тогда я могу пройти через это на процессоре.
Опираясь на модульность кода, вы также можете попробовать написать для него unittest и сравнить результаты между запуском GPU и CPU. Однако вы должны знать, что в некоторых случаях C ++ может вести себя не так, как GLSL, что дает ложные срабатывания в этих сравнениях.
Наконец, когда вы не можете воспроизвести проблему на другом устройстве, вы можете начать копать только там, где возникает разница. Юниттесты могут помочь вам определить, где это происходит, но, в конце концов, вам, вероятно, понадобится записать дополнительную отладочную информацию из шейдера, как в ответе cifz .
А для краткого обзора приведу блок-схему моего процесса отладки:
В заключение приведу список случайных плюсов и минусов:
профессионал
против
источник
Хотя кажется, что на самом деле невозможно пройти через шейдер OpenGL, возможно получить результаты компиляции.
Следующее взято из образца картона Android .
Если ваш код компилируется правильно, то у вас нет другого выбора, кроме как попробовать другой способ сообщить вам о состоянии программы. Вы можете сигнализировать, что часть кода была достигнута, например, путем изменения цвета вершины или использования другой текстуры. Что неудобно, но пока кажется единственным выходом.
РЕДАКТИРОВАТЬ: Для WebGL, я смотрю на этот проект , но я только что нашел его ... не могу ручаться за это.
источник
Это копия моего ответа на тот же вопрос в StackOverflow .
Внизу этого ответа приведен пример кода GLSL, который позволяет выводить полное
float
значение в виде цвета, кодируя IEEE 754binary32
. Я использую его следующим образом (этот фрагмент выделяетyy
компонент матрицы вида модели):После того, как вы получите это на экране, вы можете просто взять любой палитру цветов, отформатировать цвет как HTML (добавив
00
кrgb
значению, если вам не нужна более высокая точность, и сделав второй проход, чтобы получить младший байт, если вы это сделаете), и Вы получите шестнадцатеричное представлениеfloat
как IEEE 754binary32
.Вот фактическая реализация
toColor()
:источник
Решение, которое сработало для меня, - это компиляция шейдерного кода на C ++ - как уже упоминал Nobody. Он оказался очень эффективным при работе со сложным кодом, хотя и требует небольшой настройки.
Я работал в основном с HLSL Compute Shaders, для которых я разработал библиотеку для проверки концепции, доступную здесь:
https://github.com/cezbloch/shaderator
Он демонстрирует на вычислительном шейдере из примеров DirectX SDK, как включить отладку на C ++, например HLSL, и как настроить модульные тесты.
Компиляция вычислительного шейдера GLSL в C ++ выглядит проще, чем HLSL. Главным образом из-за синтаксических конструкций в HLSL. Я добавил тривиальный пример Исполняемого модульного теста на GLSL ray tracer Compute Shader, который вы также можете найти в источниках проекта Shaderator по ссылке выше.
источник