- PVSM.RU - https://www.pvsm.ru -
Как вы, возможно, знаете в мире Windows для рисования графики часто используется DirectX. В последних версиях (10, 11.x) библиотека серьёзно шагнула вперёд и именно на них построены движки многих современных игр. Кроме того, DirectX используется не только в играх — сам интерфейс ОС Windows тоже с непомню-какой версии (Vista?) рисуется через него, да и казалось-бы не сильно связанные с графикой программы, желая увеличить производительность и плавность зумаскрола переходят на последние версии DirectX. Так некоторое время назад на DirectX11 перешел рендер Google Chrome (вроде бы с версии 36).
Когда-то во времена Windows 95 и Pentium II была такая шутка, что чем медленнее компьютер — тем лучше можно понять работу операционной системы — невооруженным глазом видно в каком порядке прорисовываются элементы окон, обрабатываются события. Сегодня для подобных целей относительно DirectX есть отдельные инструменты — графические отладчики, позволяющие понять, как именно рисуется каждый пиксель каждого кадра, какие операции выполняет движок DirectX, какие ресурсы он использует, насколько быстро и правильно всё работает. Один из таких инструментов — RenderDoc от компании Crytek мы сегодня и рассмотрим. А в качестве примера разберём уже упомянутый выше новый рендер Google Chrome.
Прежде всего — почему я говорю о RenderDoc? Есть немало аналогичных инструментов:
Все они — очень хороши. Но:
Что касается RenderDoc, то это:
Итак, качаем RenderDoc [6], устанавливаем. Запускаем, видим главное окно. Открываем в меню Tools->Options и указываем папку, в которую будут складываться временные файлы (дампы).
Теперь нам нужно запустить под отладчиком RenderDoc приложение, которое мы хотим отлаживать. Для этого на вкладке "Capture Executable" вводим путь к Chrome, его рабочую папку. Здесь есть несколько интересных моментов. Графика в Хроме рисуется в отдельном дочернем процессе, его можно определить запустив Process Hacker и найдя среди всех запущенных процессов chrome.exe тот, у которого среди параметров командной строки имеется флаг --type=gpu-process.
Мы не можем запустить этот процесс напрямую, поэтому мы должны запустить главный процесс Chrome, указав в RenderDoc, что хотим отслеживать вызовы DirectX-функций в том числе среди дочерних процессов (галочка Hook Into Children)
По-умолчанию дочерние процессы Chrome «живут» в песочнице — имеют низкий Integrity Level, который препятствует их взаимодействию с файловой системой, другими процессами и общими ресурсами ОС. Таким образом, если мы просто запустим Chrome, то RenderDoc не будет в состоянии взаимодействовать с процессом, в котором рисуется графика. Для этого есть хак — Chrome нужно запускать со специальным флагом --no-sandbox, который отключает «песочницу» Chrome.
Поскольку нам интересно вообще всё, что будет происходить по ходу рисования графики — включаем побольше разных полезных галочек. Также мы можем сразу указать, какой по счету фрейм мы хотим захватить (для этого есть галочка Queue Capture Of Frame #), а можем уже в приложении нажать кнопку PrintScreen, чтобы создать дамп для текущего кадра
В итоге вкладка Capture Executable у нас будет выглядеть вот так:
Жмём кнопку Capture, запускается Chrome.
В верхней части окна мы видим некую отладочную информацию, которая говорит нам как-минимум о нескольких вещах:
Теперь можно открыть в Chrome что-нибудь и нажать PrintScreen. В верхней части окна Chrome появится надпись о созданном скриншоте. Всё, Chrome можно закрывать, а в папке, которую вы указали в настройках должен появиться файл с расширением rdc. Это и есть наш дамп. Открываем его через "File->Open Log" и видим примерно вот такую картину:
В верхней части окна находится «таймлайн» — временная линия, на которой отмечены этапы рисования данного кадра. Их может быть до нескольких десятков (если вы их не видите — кликните по плюсику в левом верхнем углу окна «Timeline»). Те же этапы отмечены в панели "Event Browser" в левой части окна. Кликая по таймлайну или по событиям в «Event Browser» мы можем переходить к разным моментам по ходу рисования кадра.
Корневой узел дерева событий называется "Frame #N" и показывает, какой это кадр от момента инициализации DirectX в приложении. Далее следует мета-узел "Frame start" указывающий на момент начала рисования данного кадра (никаких реальных вызовов DirectX-методов к нему не привязано). Далее мы видим три узла: "Colour Pass #1 (1 Targets)", "Draw(4)" и "Present()". Из этого мы можем понять, что всё рисование контента окна хрома проходит в несколько этапов:
Как видите, этап рисование в промежуточную текстуру в дереве можно раскрыть и мы увидим моменты рисования отдельных элементов окна Хрома.
Первым делом текстура очищается (вызов ClearRenderTargetView). Затем следует много этапов под названием "DrawIndexed(6)". 6 — это количество точек, ограничивающих область, рисуемую на данном этапе. То, что их 6, наталкивает на мысль, что это 2 треугольника, составляющих прямоугольник. Давайте выберем один их этапов "DrawIndexed(6)" (не первый, но и не последний) и рассмотрим его повнимательнее.
Начнём с вкладки "Pipeline State"
Как вы, возможно, знаете, в DirectX11 используется понятие «Pipelene» — это набор из нескольких последовательных операций, предназначенных для формирования окончательного кадра. Начинается пайплайн с этапа Input Assembler — здесь мы предоставляем все необходимые входные данные по вершинным, индексным и константным буферам, которые могут в дальнейшем понадобиться для рассчёта что и куда нужно будет рисовать. Далее следуют этапы обработки входных данных различными типами шейдеров и последняя фаза — Output Merger, в которой графика компонуется и выводится туда, куда должна быть выведена.
В окне Pipeline State мы можем кликнуть по любой стадии пайплайна и увидеть:
Перейдя в окно текстур, мы можем увидеть используемые при рисовании данного кадра текстуры:
В тулбаре "PS Resources" мы видим текстуру(ы), которая будет рисоваться на данном этапе, а в тулбаре "OM Targets" — текстуру, куда будет происходить отрисовка. Оставаясь в окне текстур, можно покликать по этапам отрисовке сверху или слева — и мы увидим, что Хром рисует своё окно текстурами размером 256х256 пикселей. Начинает он с нижней части окна, потом рисует боковые края и затем — заголовок окна с тулбарами. После этого Хром приступает к рисованию контента вкладки (опять-таки кусочками по 256х256 пикселей). Потом рисуются лежащие «поверх» контента объекты — видео, флеш-баннеры, всплывающие подсказки. На последних этапах рисуются скроллбар и его ползунок. Теперь текстура готова к рисованию в бэкбуфер.
Показывать API вызываемых DirectX-методов для каждого этапа отрисовки
Невероятно полезная вещь. А учитывая, что видны не только названия методов, но и их параметры — это вообще красота.
Показывать колстек (откуда в коде был вызван тот или иной DirectX-метод)
Правда, для этого нужно подсунуть программе pdb-файл (который у вас есть только если вы сами — автор отлаживаемого кода). Весьма полезно для отладки своих программ, полностью бесполезно для анализа чужих.
Дебажить шейдеры
Для вершинных шейдеров отладка начинается в окне Mesh Output с клика правой кнопкой мыши по интересующей вершине.
Для пикселей — в окне текстур, где на интересующем пикселе нужно кликнуть правой кнопкой мыши и кликнуть в тулбаре "Pixel Content" кнопку "Debug this Pixel"
Вот такой полезный инструмент RenderDoc.
Удачной вам отладки графики.
Автор: tangro
Источник [7]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/news/68335
Ссылки в тексте:
[1] PIX: http://en.wikipedia.org/wiki/PIX_(Microsoft)
[2] Intel Graphics Performance Analyzers: https://software.intel.com/en-us/vcsource/tools/intel-gpa
[3] AMD GPU PerfStudio 2: http://developer.amd.com/tools-and-sdks/graphics-development/gpu-perfstudio-2/
[4] NVIDIA® Nsight™ Development Platform: https://developer.nvidia.com/nsight-visual-studio-edition-features
[5] Visual Studio Graphics Diagnostics tools: http://msdn.microsoft.com/en-us/library/hh873207(v=vs.110).aspx
[6] качаем RenderDoc: http://crydev.net/dm_eds/files/General_Downloads/RenderDoc_20.zip
[7] Источник: http://habrahabr.ru/post/234619/
Нажмите здесь для печати.