Я люблю графические отладчики. Обычные я тоже люблю, но графические — больше. Они дают ощущение сродни заглядыванию за кулисы театра во время выступления: «ага, вот эта декорация крепится так, а этот луч света падает отсюда, а у этого шкафа нет задней стенки...». Графический отладчик пробрасывает мостик понимания между текстовым кодом приложения и полученной красивой картинкой.
Но индустрия не балует нас обилием подобного инструментария. Есть графические отладчики от Intel, NVidia и AMD, но они не работают на чипах конкурентов и предназначены не столько для разработки\отладки, сколько для бенчмарков и хвастовства своими видеокартами. Они неплохо рассказывают ЧТО и КОГДА произошло, но плохо объясняют ПОЧЕМУ и КАК ИСПРАВИТЬ.
В другом лагере находится мой любимый RenderDoc, о котором я уже писал. Прекрасная утилита, написанная ребятами из Crytek для себя и людей. Открытый код, поддержка всех вендоров, DirectX11 (с планами на Вулкан и DirectX12), куча мелких полезных мелочей.
Вторым представителем когда-то был PIX — утилита для анализа производительности DirectX9. Задумывалась она как инструмент для разработки под XBox (само название это аббревиатура от Performance Investigation for XBox), но хорошо работала и для десктопных приложений. До того момента, пока не умерла (с выходом DirectX 10/11 и новых версий Windows). Microsoft, у которого в очередной раз маркетологи победили инженеров, объявил единственным инструментом для графической отладки Visual Studio, в которой именно для этих целей было много лишнего, многого не хватало, а кое-что было и вовсе невозможно. Студия — прекрасный инструмент для программирования, но далеко не столь хорошая вещь для изучения, профилирования и отладки графического кода (тем более чужого).
Всё это уныние продолжалось несколько лет, пока инженеры Microsoft не одержали временную победу и в январе 2017 года Microsoft объявила о запуске беты полностью обновлённой версии PIX для DirectX 12!
Давайте же посмотрим, что мы получили.
Вам понадобится Windows 10 (для использования DirectX 12). Сам PIX можно скачать вот отсюда. Ну и ещё вам понадобиться приложение, которое что-то рисует с помощью DirectX 12. Для начала можно взять, например, официальные примеры от Microsoft, вот они на GitHub. Для их сборки понадобится Visual Studio (2015 или новее, бесплатная Community вполне подойдёт) и Windows 10 SDK.
Качаем и устанавливаем всё вышеперечисленное, собираем примеры, запускаем PIX.
Стартовое окно PIX выглядит хорошо. Есть что-то от последних версий Office, что-то от Visual Studio и совсем мало от модного нынче в Microsoft стиля приложений UWP. Сходу нам предлагают заняться одним из шести действий на выбор: GPU Capture и Timing Capture относятся к графическому адаптеру, остальные пункты — к обычному профилированию, которое нам в контексте данной статьи малоинтересно.
Необходимость наличия двух пунктов GPU Capture и Timing Capture, как объяснил в презентации один из разработчиков PIX, продиктована тем, что нет никакой возможности одновременно и узнать детальное состояние графического пайплайна и сохранить неизменными тайминги, поскольку доступ к чему-то одному изменяет второе (в этом месте в качестве иллюстрации было приведено уравнение Гейзенберга :) ). Поэтому в каждом конкретном случае придётся выбирать, хотим ли мы сейчас отлаживать производительность или точность отрисовки.
Для замеров производительности у нас есть утилиты вендоров, поэтому сосредоточимся на GPU Capture. Нам предлагают либо запустить одно из установленных на данном компьютере UWP-приложений, либо указать путь к бинарнику обычного. Есть также вкладка Attach, но она не по нашу душу — работает только для обычного профилирования, а вот именно графическая отладка включится лишь для запущенного из-под PIX приложения. Это, кстати, создаёт проблему с лаунчерами (которая в Renderdoc, например, решена). Ну, может когда-нибудь и здесь пофиксят.
Я для экспериментов взял вот этот пример — он простой, как дверь, и в то же время позволяет продемонстрировать всё необходимое, поскольку делает достаточно много вызовов отрисовки.
Судить о том, что PIX успешно внедрён в приложение можно по надписи в верхней части кадра. Теперь нужно сделать «снимок» отрисовки одного кадра — с помощью PrintScreen в запущенном приложении или кнопкой с фотоаппаратом из PIX. Захваченный снимок выглядит вот так:
Открываем снимок. Видим порядок операций отрисовки кадра:
Внизу есть таймлайн, но на нём ничего нет. Это не баг, а фича. Для того, чтобы там что-то появилось, нужно запустить «воспроизведение» снимка (кнопка «Start» справа вверху). Тогда PIX восстановит в памяти все ресурсы, необходимые для отрисовки и вызовет все методы (в том же порядке, с теми же параметрами). И вот наш таймлайн.
Здесь можно оценить производительность, параллельность ну и в целом общую картину. Выбрав определённый вызов отрисовки, можно перейти на соседнюю вкладку Pipeline и посмотреть, что же там рисовалось.
Мы можем просмотреть состояние входных буферов, привязанные текстуры и шейдеры, результат отрисовки после выполнения данного вызова:
Кликнув правой кнопкой мыши где-нибудь по картинке можно посмотреть историю отрисовки данного пикселя:
Мы видим, что данный конкретный пиксель при отрисовке текущего кадра был затронут дважды — при очистке полотна и при отрисовке текстуры «шашечек» позже.
Из контекстного меню любого шага в истории отрисовки можно запустить отладку шейдера, который рисовал данный пиксель:
Отладчик хороший — можно идти по шагам, пользоваться точками останова, возвращаться назад, в окне Autos видны все необходимые значения. Есть даже Edit & Continue для кода шейдера.
В общем новый PIX мне понравился. Есть мелкие шероховатости (отсутствие поддержки лаунчеров, работа только с одним GPU), но это всё поправимо. Из глобальных недостатков я бы отметил лишь отсутствие поддержки DirectX 11 — это ещё очень распространённый стандарт и отсутствие его поддержки как в старой, так и в новой версии PIX весьма расстраивает.
Но индустрия не балует нас обилием подобного инструментария. Есть графические отладчики от Intel, NVidia и AMD, но они не работают на чипах конкурентов и предназначены не столько для разработки\отладки, сколько для бенчмарков и хвастовства своими видеокартами. Они неплохо рассказывают ЧТО и КОГДА произошло, но плохо объясняют ПОЧЕМУ и КАК ИСПРАВИТЬ.
В другом лагере находится мой любимый RenderDoc, о котором я уже писал. Прекрасная утилита, написанная ребятами из Crytek для себя и людей. Открытый код, поддержка всех вендоров, DirectX11 (с планами на Вулкан и DirectX12), куча мелких полезных мелочей.
Вторым представителем когда-то был PIX — утилита для анализа производительности DirectX9. Задумывалась она как инструмент для разработки под XBox (само название это аббревиатура от Performance Investigation for XBox), но хорошо работала и для десктопных приложений. До того момента, пока не умерла (с выходом DirectX 10/11 и новых версий Windows). Microsoft, у которого в очередной раз маркетологи победили инженеров, объявил единственным инструментом для графической отладки Visual Studio, в которой именно для этих целей было много лишнего, многого не хватало, а кое-что было и вовсе невозможно. Студия — прекрасный инструмент для программирования, но далеко не столь хорошая вещь для изучения, профилирования и отладки графического кода (тем более чужого).
Всё это уныние продолжалось несколько лет, пока инженеры Microsoft не одержали временную победу и в январе 2017 года Microsoft объявила о запуске беты полностью обновлённой версии PIX для DirectX 12!
Давайте же посмотрим, что мы получили.
Настройка окружения
Вам понадобится Windows 10 (для использования DirectX 12). Сам PIX можно скачать вот отсюда. Ну и ещё вам понадобиться приложение, которое что-то рисует с помощью DirectX 12. Для начала можно взять, например, официальные примеры от Microsoft, вот они на GitHub. Для их сборки понадобится Visual Studio (2015 или новее, бесплатная Community вполне подойдёт) и Windows 10 SDK.
Качаем и устанавливаем всё вышеперечисленное, собираем примеры, запускаем PIX.
Начало работы
Стартовое окно PIX выглядит хорошо. Есть что-то от последних версий Office, что-то от Visual Studio и совсем мало от модного нынче в Microsoft стиля приложений UWP. Сходу нам предлагают заняться одним из шести действий на выбор: GPU Capture и Timing Capture относятся к графическому адаптеру, остальные пункты — к обычному профилированию, которое нам в контексте данной статьи малоинтересно.
Необходимость наличия двух пунктов GPU Capture и Timing Capture, как объяснил в презентации один из разработчиков PIX, продиктована тем, что нет никакой возможности одновременно и узнать детальное состояние графического пайплайна и сохранить неизменными тайминги, поскольку доступ к чему-то одному изменяет второе (в этом месте в качестве иллюстрации было приведено уравнение Гейзенберга :) ). Поэтому в каждом конкретном случае придётся выбирать, хотим ли мы сейчас отлаживать производительность или точность отрисовки.
Для замеров производительности у нас есть утилиты вендоров, поэтому сосредоточимся на GPU Capture. Нам предлагают либо запустить одно из установленных на данном компьютере UWP-приложений, либо указать путь к бинарнику обычного. Есть также вкладка Attach, но она не по нашу душу — работает только для обычного профилирования, а вот именно графическая отладка включится лишь для запущенного из-под PIX приложения. Это, кстати, создаёт проблему с лаунчерами (которая в Renderdoc, например, решена). Ну, может когда-нибудь и здесь пофиксят.
Я для экспериментов взял вот этот пример — он простой, как дверь, и в то же время позволяет продемонстрировать всё необходимое, поскольку делает достаточно много вызовов отрисовки.
Судить о том, что PIX успешно внедрён в приложение можно по надписи в верхней части кадра. Теперь нужно сделать «снимок» отрисовки одного кадра — с помощью PrintScreen в запущенном приложении или кнопкой с фотоаппаратом из PIX. Захваченный снимок выглядит вот так:
Открываем снимок. Видим порядок операций отрисовки кадра:
Внизу есть таймлайн, но на нём ничего нет. Это не баг, а фича. Для того, чтобы там что-то появилось, нужно запустить «воспроизведение» снимка (кнопка «Start» справа вверху). Тогда PIX восстановит в памяти все ресурсы, необходимые для отрисовки и вызовет все методы (в том же порядке, с теми же параметрами). И вот наш таймлайн.
Здесь можно оценить производительность, параллельность ну и в целом общую картину. Выбрав определённый вызов отрисовки, можно перейти на соседнюю вкладку Pipeline и посмотреть, что же там рисовалось.
Мы можем просмотреть состояние входных буферов, привязанные текстуры и шейдеры, результат отрисовки после выполнения данного вызова:
Кликнув правой кнопкой мыши где-нибудь по картинке можно посмотреть историю отрисовки данного пикселя:
Мы видим, что данный конкретный пиксель при отрисовке текущего кадра был затронут дважды — при очистке полотна и при отрисовке текстуры «шашечек» позже.
Из контекстного меню любого шага в истории отрисовки можно запустить отладку шейдера, который рисовал данный пиксель:
Отладчик хороший — можно идти по шагам, пользоваться точками останова, возвращаться назад, в окне Autos видны все необходимые значения. Есть даже Edit & Continue для кода шейдера.
В общем новый PIX мне понравился. Есть мелкие шероховатости (отсутствие поддержки лаунчеров, работа только с одним GPU), но это всё поправимо. Из глобальных недостатков я бы отметил лишь отсутствие поддержки DirectX 11 — это ещё очень распространённый стандарт и отсутствие его поддержки как в старой, так и в новой версии PIX весьма расстраивает.