вторник, 18 мая 2010 г.

Hitler reacts to the Hitler parodies being removed

Youtube по требованию Constantin Film AG удаляет все юзверские пародии "Hitler reacts...", основой для которых послужила весьма характерная сцена из малоизвестного ранее фильма "Downfall" (у нас - "Бункер"). Если кто не в курсе, то Youtube до недавнего времени буквально лихорадило от самых разных пародий со сценой разноса высшего военного командования в бункере, в том числе и made in Russia. В ответ на эти действия появилась очередная смешливая пародия, где Гитлер узнаёт, что пародии на него самого удаляются с Youtube. Не знаю, сколько будет жить это видео, поэтому просто привожу ссылку:

Hitler reacts to the Hitler parodies being removed from YouTube

В одном авторы пародии безусловно правы: фильм "Downfall" стал популярным именно из-за пародий "Hitler reacts...", до этого о нём знали единицы, в широкий прокат картина не вышла. Я сам посмотрел этот фильм только после того, как случайно наткнулся на одну из таких пародий в прошлом году. И вот теперь Constantin Film AG так платит юзверям Youtub-a за пиар фильма.

P.S. А всё-таки видео "Hitler Fermi" было лучшее!

понедельник, 17 мая 2010 г.

Дождь

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


Я был в джинсах и лёгенькой маечке (потому что май месяц) и сильно продрог.

Packed A-buffer

В презентации AMD можно найти совет по оптимизации работы с A-буфером:

Optimize performace by reducing amount of data to write to/read from UAV.

Узел связанного списка имеет три поля типа uint - RGBA color, depth и address. Как вариант предлагается хранить цвет в формате 565 (альфа - константная) и объединить его с 16-bit depth. Таким образом можно сэкономить один uint. Следуя по стопам приверженцев deferred shading-а, которые любят мозгодробительные комбинации упаковки G-буфера, я решил поиграться в "упаковку A-буфера", благо начиная с SM 4.0 появилась прекрасная возможность маскировать и двигать битики на GPU.

Итак, наша цель - два uint вместо трёх, но попиксельная альфа (не константная), хорошая точность цвета и глубины. Основная возможность сжатия заключается в том, что нам не нужен полный 32-битный адрес для индексации A-буфера требуемых размеров. Это, кстати, ещё та проблема - определить, буфер каких размеров будет достаточным, и сколько бит необходимо для его адресации. Я остановился на 23 битах, т. к. в этом случае можно адресовать 8 388 608 элементов, т. е. буфер размером 1024x1024, 8x overdraw в (каждом) пикселе. Думаю, для спрайтов, огня и дыма этого будет вполне достаточно. Для значения глубины я решил отвести демократичные 16 бит (такая точность иногда использовалась для буфера глубины). Т. к. у нас свободны 9 бит второго поля, которые ранее занимал адрес, то теперь в них можно поместить старшие 9 бит глубины.

Младшие 7 бит придётся делить с цветом в первом поле. Значит, под цвет остаётся 25 бит. Для последнего я решил выбрать "дьявольский" формат хранения 666_7, т. е. для RGB компонентов отводится по 6 бит, для альфы - 7. Считаю, что бандинг альфы при большом overdraw может привести к ухудшению transparency, поэтому необходимо хранить альфу как можно большей точности, к тому же в этой раскладке нет перекосов с точностью RGB-компонент.

Возможны варианты. Например, рядом со мной стоит iMac, монитор которого поддерживает разрешение 2560x1440. Не думаю, что даже hi-end видеокарты смогут быстро работать с A-буфером такого разрешения, но надо смотреть в будущее. Лучшим подходом будет на практике замерять, сколькими элементами оперирует A-буфер, для этого в Direct3D 11 можно воспользоваться методом ID3D11DeviceContext::CopyStructureCount(). Если 23 бит окажется недостаточно для адресации, можно выделить дополнительные два бита, понизив на один бит точность глубины и точность альфы цвета. Но при любой раскладке, вполне реально сэкономить одно поле в узле списка, при минимальных потерях в качестве рендеринга. А это значит, что можно сэкономить треть отводимой под A-буфер видеопамяти и ускорить чтение/запись.

Обновлённое демо: oit_packed_dx11

Update: HD 5850, прирост скорости составляет 5-10%, значит, bottleneck в сортировке. Ну хоть видеопамять сэкономил, она ведь не резиновая.

среда, 12 мая 2010 г.

A-buffer through per-pixel linked lists

Написал новую демку OIT, использующую предложенную ATI методику работы с A-буфером.

Ссылка: oit_ppll_dx11.

Доступны четыре режима: стандартный блендинг, A-буфер с построением префиксной суммы, A-буфер с построением связанных списков, K-буфер. Отлаживал в reference rasterizer на своём ноутбуке.

Как и ожидалось, подход ATI оказался более эффективным. Тестирование на HD 5850 в разрешении 1024x1024 показало прирост скорости в районе 2x-3x. Для более сложных моделей с высоким overdraw отрыв должен быть ещё больше.

Я применил одну банальную оптимизацию для снижения GPR usage. В A-буфере цвета теперь упакованы в uint, и в шейдере сортировки массив цветов, определённый как float4 a[8] заменён на uint a[8], что позволяет оперировать существенно меньшим объёмом данных при сортировке. Распаковка цвета осуществляется непосредственно перед смешиванием. GPU Shader Analyzer показывает такие цифры для Cypress (5870):

Вариант с float4 - 36 GPR, 125 ALU.
Вариант с uint - 26 GPR, 100 ALU.

Для сортируемых массивов малого размера это даёт хоть и небольшой, но всё же прирост скорости. Думается, для массива из 64 элементов прирост скорости будет ощутимым, т. к. без оптимизации мультипроцессор GPU может упереться в величину регистрового файла.

Как ещё одно средство оптимизации сортировки сложных моделей можно предложить маскировать стенселем участки кадра с разным overdraw и запускать несколько сортирующих шейдеров, рассчитанных на определённое количество слоёв (8, 16, 32, 64). Это должно быть быстрее, т. к. максимальный overdraw обычно достигается редко.

Досадным фактом является то, что сортировка методом K-буфера даёт артефакты в изображении, при том что сам алгоритм реализован без ошибок. В первый раз я списал это на проблемы "сырых" драйверов для ATI 5xxx, но теперь они вновь всплыли, уже на дискретной ATI HD 4330. Более того, отлаживая код под reference rasterizer, я обнаружил, что артефакты остаются, и это натолкнуло меня на мысль, что причина кроется в чём-то ином.

Заинтересовавшись проблемой K-буфера, я попытался локализовать причину артефактов, или хотя бы получить мнение о их природе. Я решил ограничиться двумя плоскостями и просмотреть два отрисованных слоя отдельно, без сортировки и блендинга. Вот что получилось:


На первый взгляд всё правильно, но при внимательном рассмотрении можно заметить, что второй слой растеризатор отрисовал несколько иным образом, заметны различия в ступеньках между первой перекрывающей плоскостью (красной), и перекрытой (зелёной), которая попала во второй слой. Между ступеньками есть gap:


который и порождает артефакты:


Причина подобного поведения растеризатора стала загадкой. Случайно я вспомнил, что до сих пор отлаживал код только под reference rasterizer и в feature level 10.1, тогда как мои первые реализации K-буфера работали в feature level 10.0. Я поменял level на 10.0, запустил демку и о чудо, никаких артефактов!


(Note: небольшие артефакты в месте пересечения плоскостей обусловлены тем, что задействован depth буфер с форматом пониженной точности R16_UNORM).

Переключив несколько раз feature level и убедившись, что артефакты то исчезают, то появляются вновь, я заглянул в справку DirectX SDK, а именно, в Windows Graphics/Direct3D 10/Programming Guide/Direct3D 10.1 Features. Там нашёлся следующий пункт:

Rasterization Rules - The rules for rasterization have changed for lines, in addition, new functionality has been added.

MultisampleEnable only affects line rasterization (points and triangles are unaffected), and is used to choose a line drawing algorithm. This means that some multisample rasterization from Direct3D 10 are no longer supported.

вторник, 27 апреля 2010 г.

OIT and GI using DX11 linked lists

На developer.amd.com выложены слайды с GDC 2010, их можно найти на странице GPU Technical Publications. Одна из презентаций посвящена реализации OIT (думается, в Mecha Demo) от Nick Thibieroz и Holger Grün. Краткое описание алгоритма OIT можно прочитать в блоге Вольфганга Енджела - Order-Independent Transparency II. Кроме того, доступна русскоязычная статья на uraldev-е от Евгения Коростелева: Порядко-независимая прозрачность на GPU с использованием динамических списков.

Ранее я уже пробовал разобраться в шейдерах Mecha. Для этого пришлось написать hook-DLL для перехвата вызовов D3DCompileShader(). К сожалению, все шейдеры в демо зашиты в binary blob-ы, и всё, что можно сделать - это получить дизассемблированный код. Разобраться быстро в нём оказалось непросто, т. к. код по работе с OIT был густо перемешан с кодом расчёта освещения, сортировки и т. д. Тогда я отставил эту трудоёмкую задачу, и вот теперь стали доступны детали реализации.

OIT от AMD не использует prefix scan для расчёта смещений для записи фрагментов, как это описано в патенте Microsoft. Вместо этого используется R/W structured буфер, в элементах которого хранятся атрибуты фрагмента (цвет, глубина), и индекс предыдущего (следующего, как посмотреть) фрагмента в списке (если на пиксель экрана накладываются два и более фрагментов). Индекс указывает на элемент в structured buffer. Таким образом, полупрозрачные фрагменты организуются в памяти GPU в linked lists.

Преимущество этого метода в том, что запись в structured буфер всегда происходит последовательно, даже если фрагменты в буфер кадра приходят хаотически. В противовес этому, подход, применённый в DirectX SDK (и у меня), приводит к весьма хаотичному заполнению A-буфера. Для примера, стартовые позиции двух fragment bins для двух соседних пикселей уже различны. Добавьте к этому, что растеризатор выплёвывает фрагменты не линейно, а квадами 2х2, и получается безрадостная картина неупорядоченной записи в UAV (нужно отметить, что по моим тестам, при увеличении разрешения основной bottleneck заключался именно в заполении A-буфера, за ним следовала сортировка, и только потом - относительно дешёвый prefix scan). Поэтому на практике метод AMD на шаге аккумуляции фрагментов должен работать быстрее. Правда, в дополнение также используется т. н. Start Offset Buffer, но его элементы, в которые просходит запись, находятся в тех же позициях, что и фрагменты в буфере кадра.

На этапе сортировки фрагментов происходит traversal по этим linked lists, данные из различных участков памяти собираются в массив и сортируются. Теоретически такой traversal мог бы быть медленнее, чем линейная выборка fragment bins из A-буфера, но здесь мы можем просто читать из UAV, присоединив его как shader resource view. Т. к. random access текстур в GPU хорошо оптимизирован, этот шаг, вероятно, выполняется с хорошей скоростью.

P.S. Жаль только, что не могу реализовать алгоритм - Direct3D 11 железа больше нет под рукой :(
P.P.S. Хотя можно попробовать хотя бы с софтверной эмуляцией :)

среда, 21 апреля 2010 г.

Уе

Нео: Так это и есть...
Сайфер: Что, Unreal Engine? Да.
Нео: Ты всегда смотришь на него в таком виде?
Сайфер: Приходится. У разрабов нет никакого понятия, как писать на плюсах читаемый код. Но здесь уже ничего не поделаешь, видишь, сколько всего они навалили. Ты привыкнешь к нему. Я... я даже не вижу копрокода. Я вижу только блондинку, брюнетку, рыженькую... Эй, хочешь выпить?
Нео: Ещё бы.

суббота, 17 апреля 2010 г.

X-Slim X600

- But sir, NVidia said Fermi would be 60 percent faster than Cypress.
- 60 PERCENT MY FUCKING ASS!!!

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

Мне нужен был язящный, легкий и тонкий ноутбук, плюс он должен был содержать дискретную видеокарту, поддерживающую минимум DirectX 10 (для программирования графики, иначе на кой хрен мне вообще нужен ноут?). Комбинация весьма своеобразная, но к счастью, оказалось, что ноутбуки MSI серии X-Slim X600 удовлетворяют всем этим требованиям.

И вот наконец-то я её приобрёл. Мне очень хотелось бело-серебристую модель, т. к. она выглядит весьма эффектно. Но как выяснилось, в Гондурас поставляются только чёрные, а серебристые можно купить, например, в США :(

Вот фотки ноута (качество не очень получилось, но всё же):


Я взял вариант с процессором Intel Celeron ULV, т. к. не хочется переплачивать за Core Solo - я не планирую использовать эту машинку в играх или тяжёлых приложениях, к тому же, надеюсь, это не последний ноутбук, который я приобретаю, а устаревают они очень быстро. Видеокарта - дискретная ATI Radeon HD 4330. Cоответственно, у меня теперь есть доступ к Direct3D 10.1 (я уже прогнал её через DirectX SDK, скорость в общем приличная, жаль только MSAA до 4x). Кстати, она начинает довольно сильно шуметь, когда увеличивается нагрузка на графический чип, но тут уж ничего не поделаешь.

И напоследок о весе. Вес - ~2.1 кг, что намного меньше, чем у среднестатистического "чемоданчика" (~3 кг). Достигнуто это тем, что убран привод DVD-дисков (зато в комплекте идёт флешка на 4 GB). И всё же даже 2 кг по моим ощущениям это многовато для стильной портативной машинки, оптимально, как мне кажется, 1.5 кг (MacBook Air - 1.36 кг)

P.S. А недавно узнал, что MSI готовится выпустить новую модель X400 с дискретной видеокартой, поддерживающей DirectX 11.