пятница, 18 ноября 2011 г.

OnLive

У нас в офисе появилось вот такое примечательное устройство:



Это OnLive(R) Microconsole TV Adapter. Подключается к TV через разъём HDMI, а к геймпаду- через переходник USB/mini-USB. Кабелёк коротенький, приходится держать консоль на коленях.


У этого экземпляра уже есть аккаунт на серверах OnLive, так что можно играть. Я для пробы поиграл в Splinter Cell: Conviction и Prince Of Persia: The Fogotten Sands.











Качество изображения на 40-дюймовом телевизоре вполне хорошее, артефактов сжатия я не заметил, возможно их видно только на мониторе, или же железо консольки "старается" убрать все огрехи. Чувства, что ты смотришь YouTube в 240p, не возникает. Частота кадров - по мне где-то 20-25, точнее сказать затруднительно. Есть небольшой лаг ввода, но гораздо меньше чем я ожидал, когда начинал играть. Целиться конечно неудобно, консольный геймпад+специфика доставки контента сообща работают против этого. Да и вообще игрок я никудышный :)

В общем, я думаю, что это будущее игровой индустрии. Пройдут годы, Сеть разрастётся оптоволокном, уменьшится пинг и такие вот решения станут вполне жизнеспособны. А если есть хороший интернет, в казуальные и пошаговые игры можно играть уже сейчас. По сути приход on-line моделей доставки контента неизбежен, как неизбежным стало и появление многочисленных торрентов-трекеров в середине 2000-x. Сеть породила массовое пиратство, она же его и убъёт.

четверг, 17 ноября 2011 г.

Чикса на Лексусе

Вчера я ехал на работу
в метель, туман и гололёд,
вдруг мимо пронеслась Тойота,
взяла опасный поворот.

Пересекая автостраду
там, где сплошная полоса,
водитель мазалась помадой
и тушью красила глаза!

Как тут от злости не беситься?
Я в гневе бритву уронил
(я дома не успел побриться
и по дороге щёки брил).

Упала бритва в кофе прямо
(между колен стоял стакан -
мне вкусный кофе варит мама -
его я пью в такой туман ).

Когда предмет тяжёлый падал,
крутой горячий кипяток
плеснул туда, куда не надо -
там третьей степени ожог.

И вот от боли я подпрыгнул,
и из моей руки другой
вдруг выпал телефон мобильный -
и снова - в кофе по прямой.

Не помню, что там дальше было...
Открыл глаза: больница? морг?
Теперь ни тачки, ни мобилы...
Зато повязка между ног.

Весь загипсован под завязку,
без гипса только голова.
А вот мораль у этой сказки -
У ВСЕХ БЫ БАБ ЗАБРАТЬ ПРАВА!

пятница, 11 ноября 2011 г.

Китайская грамота

Сегодня нашёл способ заставить шаблонную функцию определять размер массива.

Всё началось с того, что при программировании я использовал несколько вспомагательных шаблонных функций, вроде memzero(), которая является обёрткой над memset() и принимает один параметр вместо трёх:
template < typename T >
inline void *memzero(T *p)
{
  return memset(p, 0, sizeof(T));
}
Также я завёл один вспомогательный макрос для очистки статических С-arrays:
#define zeroarray(a) memset(a, 0, sizeof(a));
Мне хотелось оформить этот макрос тоже в виде функции, но вся загвоздка в том, что определив параметр как указатель на тип, применить к нему sizeof() нельзя. Первая попытка оформить функцию в виде шаблона выглядила так:
template < typename T, size_t N >
inline void zeroarray(T a[N])
{
    return memset(a, 0, sizeof(a));
}
Но в данном случае компилятор С++ не может вывести размер массива, и sizeof() выдаёт типичные 4 байта для 32-битной конфигурации. Тепение моё лопнуло и я полез в гугл: после 5 минут гугления выяснилось, что существует такое решение этой проблемы:
template < typename T, size_t N >
inline void zeroarray(T(&a)[N])
{
    return memset(a, 0, sizeof(T) * N);
}
Я не эксперт в С++, и мне сложно понять, что это за китайская грамота написана в виде параметра функции. Понимаю только одно - выглядит фигово :)

среда, 9 ноября 2011 г.

среда, 2 ноября 2011 г.

Driver Concurrent Creates

Стремление ускорить загрузку программы естественно.
Чем быстрее программа загружается, тем меньше это раздражает пользователя. Применительно к игрострою можно даже помечтать об играх, которые загружаются почти мгновенно :)

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

В отличие от своих предшественников, Direct3D 11 был спроектирован для поддержки мультипоточности. Вкратце, её поддержка заключается в двух возможностях:

1) Driver Concurrent Creates
2) Driver Command Lists

Первая функциональность позволяет создавать объекты (текстуры, буферы, шейдеры) в разных потоках, а вторая - формировать command buffer в отдельном потоке с дальнейшем "вливанием" его в общий контекст рендеринга. Обе эти функциональности опциональны и зависят от видеодрайвера. Если драйвер их не поддерживает, рантайм будет их эмулировать, но без надежды получить выигрыш в производительности.

В DirectX Caps Viewer в разделе "DXGI 1.1 Devices \ Reference \ Direct3D 11" каждый может посмотреть, поддерживает ли текущий драйвер эти "фичи" (как оказалось, утилита может привирать). Сразу скажу, что Driver Command Lists на момент написания этого поста не реализованы ни у AMD, ни у NVidia. О причинах можно только догадываться. Поддержка Driver Concurrent Creates может варьироваться от системы к системе, но обычно она присутствует.

Создание шейдеров на основе скомпилированного байткода вычислительно ресурсоёмкая задача: рантайм должен распарсить и валидировать байткод, а драйвер - соптимизировать его под конкретную архитектуру и транслировать в машинный код GPU. Использование нескольких ядер CPU в целях ускорения этой задачи оправданно, и если драйвер Direct3D 11 поддерживает эту функциональность, её можно задействовать.

Я решил поиграться с мультипоточной загрузкой шейдеров и написал небольшое тестовое приложение. Исходный код расположен здесь (проект для Visual Studio 2008). Суть его проста: сравнить время загрузки одного и того же количества шейдеров используя один и несколько потоков. Для начала я скрестил Win32 и консольное приложения: нет окна и обработчика оконных сообщений, зато есть консоль с HWND. Для инициализации Direct3D достаточно просто создать устройство, во всём остальном нет надобности. Далее я взял несколько простых шейдеров из состава DirectX SDK, байткод которых заставил грузиться в цикле энное количество раз. Для простоты количество создаваемых потоков равно количеству физических ядер CPU, т. е. по одному на ядро. В конце время выполнения обоих тестов сравнивается и подсчитывается фактор ускорения (он может плавать, что естественно).

С установленными видеокартами (и драйверами) AMD для Core 2 Quad я получил ускорение приблизительно 1.8X, для Core i5 - 2X-2.5X. Что интересно, для NVidia ускорение составляет ~3X, при этом скорость создания шейдеров значительно медленнее, чем в случае с AMD. Не четырёхкратное ускорение, конечно же, но и эти показатели неплохи. Интересно было бы запустить тест на новых 8-ядерных FX-81xx от AMD. Если кому-то выпадет такая возможность - пишите. Также неплохо попробовать использовать в тесте более разнообразные и тяжёлые пиксельные и вычислительные шейдеры.

P.S. Не пытайтесь запускать программу из-под отладчика - в этом случае она ведёт себя некорректно.