Хабрахабр

[Перевод] История первого GPU: Rendition Vérité 1000

image

Есть много хорошей литературы о движке Quake: книги, бесчисленные статьи в Интернете, блоги и вики-страницы. Среди них всех моими любимыми остаются «Graphics Programming Black Book» Майкла Абраша, опубликованная в 1997 году, и «Rocket Jump: Quake and the Golden Age of First-Person Shooters» Дэвида Л. Крэддока (2018 год).

Внутри архитектуры и конструкции этих кусков кремния заключена история технологической дуэли между Rendition V1000 и 3dfx Interactive Voodoo. К сожалению, можно найти очень мало информации о разработанном примерно в 1996 году оборудовании, позволившем улучшить 3D-рендеринг и, в частности, графику революционной игры id Software.

V1000 была быстрой картой, способной запускать Quake с аппаратным ускорением, обеспечивающим, по заявлению разработчика, скорость заполнения 25 мегапикселей/с[1]. После выпуска vQuake в начале декабря 1996 года казалось, что преимуществом завладела Rendition. Но, как показала история, изъян в конструкции Vérité 1000 оказался смертельным для инновационной компании.
Прямо перед Рождеством Rendition захватила рынок, позволив игрокам запускать игру с высоким разрешением, частотой кадров и в 16-битном цвете[2].

Правильно подобранное время и убойные приложения

Идея специализированного оборудования для ускорения графики появилась не внезапно. Ещё в 1954 году у авиакомпании United Airlines были симуляторы полёта для тренировок пилотов. Крупнейший игрок в этой области, Silicon Graphics, Inc. (SGI), появился ещё в 1982 году и предлагал в то время мощные рабочие станции, такие как Indy, O2 и Indigo². Однако цены на эти машины не позволяли приобретать их обычным потребителям (SGI Infinite Reality 1993 года могла продаваться за 100 тысяч долларов, что эквивалентно 177 262 долларам 2019 года). Причиной ситуации, возникшей в конце 90-х, стало сочетание трёх факторов.

Во-первых, значительно снизилась цена на ОЗУ. Даже несмотря на то, что в 1995 году появился огромный дефицит ОЗУ (в основном потому, что для ОС Microsoft Windows 95 рекомендовалось 8 МБ памяти), за год цена ОЗУ упала почти на 90%. Это открыло перспективы для карт с потрясающе огромными буферами кадров (640x480 с 16-битным RGB-цветом), способными хранить текстуры локально.

FastPage RAM была шагом вперёд по сравнению с DRAM, но после выпуска EDO RAM задержки снизились на 30%, а время доступа к ОЗУ составило 50 нс[3]. Во-вторых, повысилась производительность ОЗУ.

У PC появились мощные ЦП, например, Intel Pentium с частотой 166 МГц, которые разработчики использовали для создания высококачественных 3D-игр. Третьим и последним куском головоломки стали «убойные приложения» (killer apps). В 1996 году все говорили о двух играх: Tomb Raider компании Core Design и Quake от id Software.

Rendition и V1000

Rendition Inc была основана в 1993. Два года спустя, в 1995 году, компания объявила о создании архитектуры V1000, которая быстро была лицензирована четырьмя OEM. Первыми на рынке появились Creative Labs 3D Blaster PCI, Sierra Screamin' 3D, Canopus Total 3D и Intergraph Reactor, а вскоре за ними в дело вступила компания MiRO.

Intergraph Reactor. Изображение с vgamuseum.ru.

Creative Labs 3D Blaster. Изображение клуба «Retro Graphics Cards».

Заметьте, что первый чип V1000-E был позже заменён на V1000L-P с меньшим энергопотреблением и на 20% быстрее[4].

MiroCrystal VRX. Изображение с vgamuseum.info.

Canopus Total3D. Изображение с vgamuseum.ru.

Название карт менялось, но используемые в них чипы были одинаковыми. Единственным параметром, по которому производители должны были балансировать цену и производительность, оставалось качество установленной на карте ОЗУ.

  1. VGA-порт для подключения к ЭЛТ-монитору.
  2. Ramdac, обычно от Bt, но иногда и чип AT&T.
  3. Ядро карты — чип V1000-E, V1000-P или v1000-L.
  4. Восемь 512 кибибайтных чипов DRAM/EDO (в сумме 4 мебибайта) для хранения буферов кадров и текстур.
  5. 64 кибибайта EEPROM, содержащие BIOS.

V1000 имела два неотъемлемых свойства, которые важно отметить, потому что в 3dfx Voodoo (которую я рассмотрю позже) использовался радикально иной подход.

Чип поддерживал отрисовку и 2D, и 3D в VGA, а благодаря переключателям контекста имел впечатляющий режим «3D в окне». Во-первых, карта должна была стать заменой тому, что уже установлено у покупателя. Поэтому у карты был единственный выходной VGA-порт.

64-битная шина данных между ними не имела никаких особых свойств. Вторая особенность — это архитектура «big iron», основанная на одном ЦП Mips, получающем доступ ко всем 4 мебибайтам памяти. Такая стандартизованная конструкция позволяла с лёгкостью программирования карту с помощью загружаемого при запуске микрокода (это превратило карту в первый GPU для PC, задолго до того, как Nvidia придумала это определение.)

Программирование V1000

SDK[5] поставлялся с набором файлов заголовков для взаимодействия с языком C (RRedline в Windows и Speedy3D в DOS). Отрисовка текстурированного треугольника напоминала то, что обеспечивает сегодня Vulkan с ручным управлением VRAM. API, способный рендерить текстурированные треугольники с учётом ракурса, также поддерживал альфа-тесты, альфа-смешение и туман.

#include <string.h>
#include <windows.h>
#include <redline.h> WinMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR cmdLine, int cmdShow){ int WIDTH=640, HEIGHT = 480; HWND hWndMain = ... ; // Setup Verite board and resolution/refresh rate v_handle verite; VL_OpenVerite(hWndMain, &verite); V_SetDisplayType(verite, V_FULLSCREEN_APP); V_SetDisplayMode(verite, WIDTH, HEIGHT, 16, 75); // Copy texture to VRAM bmp_info bmp = loadBMP("data\\rlogo.bmp"); v_memory memObj = V_AllocLockedMem(verite, bmp.linebytes*bmp.height); memcpy(V_GetMemoryObjectAddress(memObj), bmp.addr, bmp.linebytes*bmp.height); v_surface *display, *texture; VL_CreateSurface(verite, &display, V_SURFACE_PRIMARY, 2, V_PIXFMT_565, WIDTH, HEIGHT); VL_CreateSurface(verite, &texture, 0, 1, V_PIXFMT_565, bmp.width, bmp.height); v_cmdbuffer cmdbuffer = V_CreateCmdBuffer(verite, 0, 0); VL_LoadBuffer(&cmdbuffer, texture, 0, bmp.linebytes, bmp.width, bmp.height, memObj, 0); VL_InstallDstBuffer(&cmdbuffer, display); VL_InstallTextureMap(&cmdbuffer, texture); VL_SetSrcFunc(&cmdbuffer, V_SRCFUNC_REPLACE) // Clear screen to black VL_FillBuffer(&cmdbuffer, display, 1, 0, 0, display->width, display->height,0); // Populate cmd with triangle coo and textCoo v_kaxyzuvq vertex[3] = ... ; VL_Triangle(&cmdbuffer, V_FIFO_KAXYZUVQ, &vertex[0], &vertex[1], &vertex[2]); V_IssueCmdBuffer(verite, cmdbuffer); VL_SwapDisplaySurface(&cmdbuffer, display);
}

RRedline обеспечивал загрузку в Vérité 128 кибибайт микрокода и транслировал вызовы C в вызовы ассемблерных функций V1000.

Однако название Speedy3D было идеей Уолта Донована. Интересный факт: название API «RRedline» обыгрывало словосочетание «Rendition Ready» и скорее всего было выбрано коллегиально.

О, и ещё инструкцию «билинейной загрузки», которая считывала блок линейной памяти размером 2x2 и выполняла билинейную фильтрацию на основе дробных значений u и v, переданных в инструкцию. По сути, v1000 всего лишь был медленным ЦП (25 МГц), имевшим однотактовое умножение 32*32 (занимавшую солидную часть чипа!), однотактовую инструкцию вычисления аппроксимированного обратного значения (то есть двухтактовое аппроксимированное целочисленное деление), и обычный набор RISC-инструкций. Поэтому если появлялся идеально совпадающий блок 2x2, мы получали уменьшение нагрузки на пропускную способность памяти. В карте был крошечный кеш, кажется, всего 4 пикселя.

Поэтому ПО, выполнявшееся в v1000, должно было считывать Z, выполнять сравнение, а затем решать, выполнять запись или нет. Аппаратная поддержка Z-буферов отсутствовала.

— Уолт Донован (архитектор алгоритмов)

Для отправки текстур и микрокода в карту драйвер использовал DMA, чтобы передавать данные по PCI без вмешательства ЦП. На практике, у многих материнских плат шинное управление не было реализовано правильно, поэтому играм приходилось возвращаться к режиму PCI FIFO, что отрицательно сказывалось на производительности[6]. Внутри карты все операции выполнялись в 32-битных целых числах с фиксированной запятой.

Поэтому если для записи пикселя нужно было 25 инструкций, то мы получим всего 1 мегапиксель/с. Разработчики решили, что Rendition будет полностью программируемым, но не использовали никакого умного конвейера или быстрой синхронизации. Сотрудники 3dfx пришли из SGI, поэтому они выбрали подход, оказавшийся правильным решением — создать в оборудовании движок обработки треугольников с фиксированным функционалом и подмножеством функций OpenGL для управления. Если использовать оборудование с фиксированным функционалом, то можно создать конвейер, эквивалентный этим 25 инструкциям, и добиться 25 мегапикселей/с. Разработчики V1000 имели совсем другой опыт, они не знали OpenGL, а поэтому решили, что правильнее будет создать ЦП.

— Уолт Донован (архитектор алгоритмов)

Кроме всего этого набора функций карта также имела инновационную систему сглаживания, обладавшей забавным побочным эффектом.

Об этом алгоритме ходила забавная шутка. Использованный в vQuake алгоритм сглаживания (антиалиасинга) был запатентован (номер патента 6005580). В Quake использовалась концепция «идеальной z-буферизации», при которой графика делилась на интервалы и визуально сортировалась с помощью BSP/PVS (двоичного разбиения пространства/набора потенциально видимых элементов). Он работал только с треугольниками, но не интервалами. Однако изначальными данными для этих интервалов были треугольники. Поэтому движок создавал набор интервалов, которые идеально покрывали экран без наложений и пропущенных пикселей, и для отрисовки требовалась единственная операция записи (без z-буферизации!) в память дисплея. (Подробнее об этой идее см. Алгоритм антиалиасинга искал рёбра силуэтов и сглаживал их. Он отрисовывал его в любом случае. сайт humus.name, запись Geometric Post-Process antialiasing примерно от марта 2011 год — автор изобрёл эту технологию заново!) Но так как сглаживание выполнялось после рендеринга экрана (все интервалы уже были отрисованы), алгоритм понятия не имел, видимо ребро или нет. (Если бы использовался z-буфер, то перерисовывались бы только видимые рёбра!) На практике это не оказалось большой проблемой, потому что BSP обычно очень хорошо отсекал невидимые треугольники.

Поэтому vquake позволял игроку видеть людей, прячущихся за дверьми и стенами, создавая небольшое и подвижное искажение в текстурах! Но не у моделей персонажей!

— Уолт Донован (архитектор алгоритмов)

vQuake

В момент выпуска карт они поддерживали несколько хороших игр. Да, Descent II, Grand Prix Legends, IndyCar Racing II, Myst, Nascar Racing, EF2000 и Tomb Raider были неплохими играми, но истинным бриллиантом в короне, самой требовательной и продвигающей продажи была Quake. Игра id Software получила собственный порт под Vérité с названием vQuake, выпущенный 2 декабря 1996 года. Он был написан Уолтом Донованом и Стефаном Поделлом из Vérité при сотрудничестве с Майклом Абрашем из id Software.

Pentium 166Mhz, способный рендерить Quake в разрешении 320x200 с частотой 26 кадров в секунду, мог перепрыгнуть на 640x480 с билинейной фильтрацией и по-прежнему рендериться с частотой 22 кадра в секунду[8]. Работа была довольно кропотливой, но порт заработал. В течение короткого промежутка времени vQuake бесспорно оставался наилучшим способом игры в Quake. На практике игроки выбирали разрешение 512x384, которое и красиво выглядело, и позволяло обеспечивать на P166 32 кадра в секунду.

image

Программный рендеринг

image

Vérité V1000

Большое спасибо пользователю @swaaye с форума vogons.org за скриншоты с V1000 и Fruit Of the Dojo за его высококачественный и простой в хакинге порт Quake на MacOSX[9].

image

Программный рендеринг

image

Vérité V1000

Изъян Z-буфера

Чего не хватало V1000 (и косвенно его преемнику V2200), так это аппаратного ускорения z-буфера. Как только разработчик включал тест глубины, скорость заполнения падала до 12,5 мегапикселей/с и частота кадров уменьшалась вдвое. Как позже объяснил Стефан Поделл[10], vQuake (и все другие игры) портировались на V1000 таким образом, чтобы минимизировать чтение z-буфера.

В случае vQuake это означало, что карта будет использоваться как сверхбыстрый рендерер горизонтальных интервалов, который всегда выполняет запись в z-буфер, но считывание и сравнение z производит только при рендеринге врагов. Разработчики выяснили, что единственным способом обеспечения нужной скорости был перенос основной части работы в ЦП. И хотя разработчикам удалось создать хорошие продукты, последствия такого выбора архитектуры аукались ещё долго.

3dfx и падение Rendition

id Software выпустила GLQuake 22 января 1997 года. Он был реализован на основе miniGL (подмножества стандарта OpenGL 1.0, в котором, среди прочего, отсутствовали GL_LIGHT и GL_FOG). Этот двоичный файл открыл двери всем картам для PC с аппаратным ускорением. В этом отношении особо выделялись карты Voodoo компании 3dfx Interactive, их потрясающие показатели (41fps в разрешении 512x384 с 16-битным цветом на P166[11]) де-факто стали эталоном для 3D-акселераторов. Скорость заполнения V1000 в 25 мегапикселей/с, которая когда-то выгодно отличалась от программного рендеринга Pentium, теперь казалась посредственной на фоне 50 мегапикселей/с карты Voodoo, на которую даже не влияли z-тесты.

Рекламировалось, что благодаря аппаратному z-буферу V2x00 была в два раза быстрее, однако ей не удалось улучшить даже частоту кадров в vQuake. Ответом Rendition стала более мощная V2x00, которая парадоксальным образом усугубила ситуацию. Эта аномалия подорвала доверие покупателей и плохо отразилась на разработчике vQuake Стефане Поделле, который чувствовал, что ему нужно объяснить, почему производительность vQuake ограничивалась ЦП, а не GPU[12].

… моя репутация оказалась подпорченной тем, что VQuake и VHexen2 не стали работать быстрее на V2x00, поэтому я должен объяснить, почему так произошло.

Более того, мы смогли бы отключить в Verite функцию сравнения по Z. Уолт и Майкл решили, что поскольку Verite 1000 не очень хорошо проявляла себя в пикселях с Z-буферизацией, то если позволить Pentium заниматься этой сортировкой интервалов, это сможет уменьшить количество пикселей, которые нужно отрисовывать Verite.

[...]

… каким бы ни был чип Verite, ЦП доставалось очень много работы.

— Стефан Поделл

Более того, присутствовали значительные проблемы аппаратной архитектуры, которые изначально приводили к выходу из строя[13] V2x00. Для устранения проблемы потребовалось несколько месяцев, и даже после этого плата всё равно работала на частоте 50 МГц, в то время как NVidia NV3 и Voodoo2 уже достигли 100 МГц.

Проект был отменён в 1998 году, после того, как компанию Rendition купила Micron Technology. Третье поколение, основанное на V3300, могло изменить курс истории, но вышло слишком поздно.

Можно было выпустить v1000 на несколько месяцев раньше (и в течение этих месяцев не иметь конкурентов), если бы мы разрабатывали схему сами, а не передали в фаб. Работая в Rendition, мы совершили много ошибок. Один парень в нашей компании потратил несколько месяцев на реализацию декомпрессии mpeg на языке ассемблера V1000, но так и не смог заставить её работать из-за непредсказуемых багов чипа. К тому же вызывал вопросы контроль качества чипа.

«Отрендерить этот список интервалов», «сгладить это ребро» — вот почти и всё, что он делал. vQuake работал хорошо только потому, что v1000 выполнял не так много работы. Мы с Майком Абрашем потратили слишком много времени на обеспечение совместимости Quake с V1000, поэтому для дальней перспективы такая модель не подходила.

— Уолт Донован (архитектор алгоритмов)

После развала Rendition компания 3dfx удвоила усилия по продвижению Voodoo2, выдающиеся характеристики которой позволили смести всех конкурентов. Король 3D-графики на PC какое-то время правил на рынке. Затем игра продолжилась, на сцене появились новые конкуренты, и среди них были канадская ATI и почти неизвестная в то время компания под названием Nvidia.

Справочные материалы

[1] Источник: VGA Museum, V1000 Texel Fillrate (MTexel/s) reported as 25

[2] Источник: John Carmack .plan Aug 22, 1996 «at 512*384 it is almost twice as fast»

1. [3] Источник: 3dfx VOODOO1 Reference Rev.

[4] Источник: Review of the V1000

[5] Источник: Rendition Verite V1000 SDK

[6] Источник: The immaturity of the PCI bus [...] caused DMA bugs to surface

[7] Источник: RRedline Programming Guide

[8] Источник: Benchmarks to compare the Rendition Vérité V1000-E and V1000L-P

[9] Источник: MacOSX X Quake port source code on github.com

[10] Источник: Stephan Podell BSS post

[11] Источник: Comparison of Frame-rates in GLQuake Using Voodoo1

[12] Источник: Stephan Podell BSS post

[13] Источник: wikipedia.com, Downfall section

Показать больше

Похожие публикации

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»