Краткий обзор архитектуры Atari Jaguar



Atari Jaguar — консоль пятого поколения, вышла в 1993 году почти одновременно с 3DO Interactive Multiplayer, но как и последняя проиграла гонку вооружений Playstation 1, которая появится годом позже.


Конструктивно можно выделить в консоли 3 главных чипа:
  • центральный процессор Motorola 68000 первых поколений, т.е. несмотря на 32-битную архитектуру памяти и регистров шина данных и ALU этого процессора 16-битные, отчего по строгости классификации его причисляют к 16-битным процессорам (как в Sega Mega Drive)
  • чип «Том» занимающийся графикой
  • чип «Джерри» занимающийся звуком
Консоль имеет 16-мегабайтное адресное пространство куда замаплены 2 Мб основной памяти, 6 Мб ROM картриджа и многочисленные порты ввода-вывода.
2 Мб основной памяти (RAM) имеет довольно сложное внутренее устройство и разводку по шинам. К ней могут с разной степенью свободы обращаться почти все компоненты системы, поэтому там создана довольно сложная система правил взаимных блокировок и распределения по разрядностям и шинам.
Так, например, ЦП m68k может обращаться к памяти только 16-битными считываниями/записями за раз как максимум. Но тот же чип «Том» может обращаться к большей части памяти как к 64-битным значениям (с другой стороны к некоторым, выделенным кускам — только как к 32-битным).
С одной стороны возможность адресовать память чипом «Том» 64-битными значениями подкрепляет позиционирование консоли как 64-битной системы, но с другой стороны ЦП может с ней обращаться только как 16-битный процессор.
Тут еще имеет место быть одна забавность — в основе своей документация использует классическую терминологию в отношении битности ячеек памяти:
  • 8-битные значения называются байтами
  • 16-битные — словами (words)
  • 32-битные — длинными словами (long words)
  • а вот 64-битные значения документация называет «фразами (phrases)», что я встречаю впервые, видимо на заре 64-битности еще толком не договорились о терминологии. сейчас такое привычно называть «четверными словами (quad words)»

Чип «Том» — графика


Графический чип «Том» сам по себе является многокомпонентной системой. Он состоит из:
  • Процессора объектов (object processor) — это единственное в системе 64-битное вычислительное ядро, но… его нельзя программировать.
  • Графического процессора (graphics processor) — программируемый 32-битный RISC-процессор — в документации он нередко называется GPU, но в современных реалиях это выглядит немного неправильно, GPU это скорее весь чип «Том» целиком.
  • Блиттера (blitter) — ядра, умеющего быстро перекидывать куски изображения в памяти с аппаратной поддержкой Z-буфера и затенения

Процессор объектов (object processor)

Именно он формирует изображение на экране. И делает это он довольно любопытным способом. Цветность может быть 16-битной (RGB или CMY(k)) или 24-битной (True Color).
В отличие от типичных ПК процессор объектов не поддерживает некоего выделенного экранного буфера который построчно выводится на экран.
Непосредственно выводится на экран только один из двух так называемых «буферов строк». Это два региона памяти в портах ввода-вывода процессора объектов размером 360 32-битных ячеек.
Если цветность видео выставлена в 24 бита, то 32-битные ячейки буферов строк отводятся под каждый пиксель выводимого изображения (8 бит не используется) и таким образом предельное разрешение по горизонтали составляет эти самые 360 пикселя.
Если же цветность выставлена в 16 бит, то каждая 32-битная ячейка буфера строки хранит по два соседних пикселя и максимальное разрешение по горизонтали становится 720 пикселей.
В каждом сканлайне процессор объектов выводит один буфер строки на экран и в это же самое время перерисовывает второй в фоне, так что на следующей строке буфера поменяются местами и выводится будет второй, а строится первый.
Построение теневого буфера строки происходит во время прохода по так называемому «списку объектов» — именно поэтому процессор объектов называется как называется.
В начале кадра в определенный порт ввода процессора объектов надо записать адрес текущего объекта в основной памяти консоли. Далее процессор объектов в каждом сканлайне делает проход по нему конструируя теневой буфер строки.
Размеры объектов всегда кратны 8 байтам (64 битам или «фразам») и они занимают от 1 до 3 фраз. Всего возможно 5 типов объектов:

1. битмап/картинка (занимает 2 фразы) — в этом объекте хранятся описание некоего битмапа в основной памяти, часть которого надо вывести на экране, а так же указатель на следующий объект в цепочке команд.
Тут используется вот какой подход — в описании объекта указано:
  • с какой позиции Y на экране он начинается по вертикали (ypos)
  • какую высоту он имеет (height)
  • в каком месте основной памяти его пиксели располагаются (data)
  • какую битность они имеют (depth) (поддерживаются 1/2/4/8 бита на пиксель через глобальную 256-цветную палитру и 16 или 32 бита на пиксель direct mode)
  • для палетризированных режимов менее 8 бит на пиксель указывается номер субпалитры внутри глобальной
  • с какой координаты по горизонтали и сколько пикселей в строке надо вывести (xpos и iwidth)
  • насколько надо увеличить указатель data (dwidth) чтобы перейти в следующей строке к следующей порции изображения
  • указатель на следующий объект в списке (link)
Так же можно отразить битмап по горизонтали.
И вот как происходит обработка таких объектов процессором объектов: пока рисуемые сканлайны еще не достигли верхнего края объекта (они меньше YPOS), то он просто пропускается пока YPOS не сравняется с номером текущего сканлайна — тогда он считается активным.
Текущая строчка (по адресу data) пикселей активного объекта рисуется в буфер строки и у объекта height уменьшается на 1 и data увеличивается на dwidth.
Когда при отрисовке следующих сканлайнов обнаружится, что height стал равен 0, то объект перестаёт считаться активным и перестаёт рисоваться — он просто пропускается.
В любом случае далее происходит переход к следующему объекту по адресу link.
Тут важно заметить, что объекты сами по себе являясь описаниями реальных картинок в памяти во первых могут ссылаться на одни и те же физические картинки, во вторых — после построения кадра им надо восстанавливать описания: уменьшенные до нуля height и инкрементированные data.
Таким образом видеочип Atari Jaguar реализует построчную отрисовку в стиле 8/16-битных консолей, но в то же время рисует он в строку сканлайна произвольные битмапы, как более мощные системы. Выделенного буфера кадра нет, потому что таким буфером кадра без ограничений может быть произвольный регион памяти. При этом с помощью прозрачности и порядка отрисовки можно накидывать их поверх друг на друга до тех пор пока по таймингам проход по списку объектов будет влазить в отрисовку сканлайна — таким образом легко реализуются произвольные спрайты в т.ч. хранящиеся в больших атласных ресурсах.

2. масштабированный битмап/картинка (занимает 3 фразы)
Всё то же самое, что и (1), но с добавкой 1 фразы где описаны коэффициенты масштабирования

3. вызов GPU (1 фраза) — процессор объектов останавливается вызывав прерывание графическому процессору. и он возобновит работу когда графический процессор даст обратный сигнал.
Эта команда позволяет процессору объектов вызвать графический процессор и подождать пока тот где-нибудь что-нибудь нарисует. что-то, что потом будет участвовать как данные в следующих командах в списке.
Важно, что графическому процессору при этом отдаётся остаток фразы самой этой команды, где можно раположить какую то полезную нагрузку-параметры.

4. переход (1 фраза)
Эта команда позволяет перенаправить обработку списка команд на какой то другой адрес в памяти — как безусловно так и по ряду условий.
В числе условий можно использовать сравнения номера текущего рисуемого сканлайна с константой или состояние программируемого бита в портах ввода-вывода процессора объектов.

5. конец (1 фраза) — на этой команде процессор объектов останавливает построение теневого буфера строки и ждёт следующего сканлайна для продолжения.

Таким образом процессор объектов являясь одновременно генератором видеосигнала так же способен выполнять задачи растрового совмещения разных изображений (как в 16-битных консолях без фактического блиттинга!) с разбиением областей экрана на разные прямоугольные области с разными данными или спрайтами.
Но если мы хотим рисовать трёхмерную графику, то этого нам недостаточно. Тут вступают в роль следующие компоненты чипа «Том».

Графический процессор (GPU)

Графический процессор несмотря на своё название на самом деле является ничем иным как 32-битным RISC-процессором с выделенными 4Кб памяти (доступными однако остальным компонентам системы, но если они к ним не обращаются, то достигается высокая степень параллельности).
Похоже что это какая то кастомная разработка, определенные корни не просматриваются, но в целом он очень типичен для философии RISC. Как можно более простое ядро (без микрокода, например) заточенное, однако на скорость работы.
Большое количество регистров — 32 для обычной работы и 32 теневых для обработки прерываний.
Простой формат инструкций и высокая степень конвееризации за счёт простого цикла обработки инструкций, арифметико-логических команд вовлекающих только регистры и работа с памятью только через инструкции load/store с простыми режимами адресации.
Присутствуют команды умножения (16-битные) и деления (32-битные), а так же быстрая битовая прокрутка (т.е. barrel shifter).
И вот тут вылезают некоторые «неаккуратности». Основная цель поставленная перед этим ядром была — скорость. Всё ради скорости и в то же время внутренней простоты.
Во первых этот процессор использовал принцип «delay slot» — это когда инструкции пытались исполнятся как можно быстрее следом друг за другом и пока одна еще только исполнялась вторая уже помещалась во внутренний буфер команд. Это приводило к тому, что даже встретив инструкцию перехода jmp процессор уже совершив даже переход всё равно обязательно следом исполнял следующую инструкцию по старому адресу, что иногда требовало размещать после инструкций холостые nop-ы:

jmp addr
nop	; эта инструкция обязательно исполнится даже после совершения перехода


Но для эффективности и плотности кода лучше было размещать там инструкции так, чтобы они всё-таки приводили к полезным вычислениям.
В силу максимальной простоты внутреннего устройства это приводило к такой проблеме, что в инструкциях следующих сразу за переходами нельзя было использовать инструкции полагающиеся на содержимое счётчика инструкций (например другие переходы), т.к. параллелизм приводил к путанице между новыми и старыми значениями до и после переходов.
Но «delay slot» был только началом — кроме этого этот процессор использовал конвееризацию — одновременное исполнение сразу нескольких инструкций потока команд в разных фазах.
Например пока одна инструкция уже производит сложение своих аргументов следующая за ней уже могла загружать свои аргументы на вход в арифметико-логическое устройство, а предыдущая уже могла сохранять какое то значение в память. Поэтому нередко производительность могла достигать 1 такта на инструкцию, хотя на самом деле это достигалось тем, что 4 инструкции выполняющиеся в разных своих фазах по 4 такта выполнялись одновременно не мешая друг-другу.
Всё это в общем то классика процессоростроения и здесь любой знакомый с предметом вспомнит, что иногда такие инструкции мешали друг другу зависимостью своих входных аргументов от выходных — иногда чтобы вычислить одну инструкцию надо было сперва дождаться пока предыдущая сохранит свой результат.
Так было и здесь. И механизм такого «разруливания» конфликтов назывался «score-boarding». Но то ли из-за спешки при разработке, то ли из-за желания максимально упростить внутреннее устройство процессора score-boarding… не всегда работал правильно.
Поэтому в официальной документации по разработке на Atari Jaguar есть раздел «Hardware Bugs & Warnings», т.е. «Аппаратные Ошибки и Предупреждения».
И там ничуть не смущаясь написано, что score-boarding в GPU получился… с багами.
Например он вообще не работал с операциями сохранения (store) с индексацией.
Это значило, что инструкции:

div r0, r3
store r3, (r14+6)


из-за того, что div выполняется очень долго (и с особой степенью параллелизма), то store успевает по стадиям проскочить вперёд и из-за того, что используется индексация (+6), то глючный score-boarding этот момент обязательно прошляпит и получится ерунда.
поэтому создатели просто сказали — вставляйте фиктивную инструкцию or r3, r3:

div r0, r3
or r3, r3
store r3, (r14+6)


с ней score-boarding уже притормозит пока результат от div не будет готов и store уже проскочит как надо.
И это далеко не единственный такой «баг» (или «фича»?). Еще нельзя было размещать инструкции деления (div) сразу друг за другом — вторая просто успевала вклиниваться своим началом в работу первой. Заглючить могли даже простые move-ы, если выпадет неприятная последовательность инструкций когда score-boarding еще мог «отказать». И многое другое. Видимо для пущего упрощения схем.
Лучше всего графический процессор работает в рамках своих «родных» 4Кб памяти. При этом он даже способен исполнять код находящийся в основной памяти, но тогда во первых просаживается скорость всей системы и опять таки начинаются какие то внутренние проблемы и «отваливаются» некоторые варианты инструкций переходов.
Поэтому правильным использованием графического процессора является загрузка в него программ и данных (причём лучше всего через блиттер, т.к. в механизме DMA оказался опять (!) какой то баг из-за которого воспользоваться им для этих целей нельзя) в его родные 4Кб и чтобы он переваривал их там.
Заодно отмечу, что на этом месте ознакомления с документацией у меня возникло стойкое ощущение, что систему сделали впопыхах и выпустили на рынок в массовом порядке не успев толком отладить и протестировать.

Блиттер (blitter)

Блиттер — это вспомогательный блок для графического процессора способный быстро переносить блоки пикселей из одного места памяти в другое с некоторой их обработкой.
Предполагается, что графический процессор должен заниматься вычислением вершин и характеристик графических примитивов, а блиттер — рисовать их пиксели.
Блиттер способен:
  • просто копировать куски памяти
  • копировать и заливать прямоугольники
  • рисовать линии
  • вращать и масштабировать изображения
  • рисовать горизонтальные линии пикселей затенённых по Гуро полигонов с Z-буфером
Таким образом чтобы рисовать те же полигоны в 3D — GPU должен вычислить из каких горизонтальных линий они состоят, какие у них параметры освещения и 3D в концах отрезков и дать команды по их отрисовке блиттеру.
Активация блиттера производится записью в его многочисленные регистры параметров с последним из них — регистром Control, что активирует выбранную функцию. Весьма похоже на программирование DMA-контроллеров в других описанных мной консолях.

Чип «Джерри»


Чип «Джерри» тоже является многокомпонентной величиной с таймерами, DMA-контроллерами, звуковыми каналами, серийными интерфейсами, портами ввода от джойстиков, но главной его компонентой является почти такой же RISC-процессор как GPU, только больше заточенный под обработку звука и называемый DSP.

Звуковой процессор (DSP)

Это почти такой же процессор как GPU, но больше заточенный под обработку звука.
Изменения включают в себя:
— увеличенный до 8Кб объём внутренней памяти
— 2Кб ROM-таблиц для синтеза звука (синусоиды, треугольные формы и т.п.)
— увеличенная точность аппаратного умножения
— несколько дополнительных инструкций для упрощения типовых задач работы со звуком

В целом консоль «изнутри» на меня произвела впечатление больше аккуратности чем тот же 3DO, но меньшей простоты для разработчика (т.к. самому надо писать программы для рисования трёхмерной графики на GPU), чем Playstation 1.

1 комментарий

avatar
В качестве бонуса еще приведу свой пост с gamedev.ru по поводу сабжа:

Те кто читал внимательно предыдущую статью про архитектуру Atari Jaguar могли заметить, что описывая блиттер консоли были упомянуты и затенение по Гуро и Z-буфер, но ничего не было сказано про текстурирование. И это действительно так — блиттер не умел текстурирование вообще.
А ведь даже современник — 3DO знал текстурирование (хотя наоборот не знал Z-буфер), но там другая история и весьма иной аппаратный ускоритель.
Действительно, если посмотреть на игру идущую в комплекте с консолью на её старте, то можно воочию увидеть, что всё 3D состояло из освещённых, но нетекстурированных треугольников:

youtu.be/dfCcgwFjlxE

Тем не менее игры с текстурированием были, но как можно понять по недолгому размышлению в этом случае игра уже не использовала аппаратный блиттер, а целиком возлагала процесс рисования треугольников на программируемое RISC-ядро чипа Том (а может даже припрягала в помощь к нему подобное ядро из чипа Джерри).

В связи с этим было интересно натолкнуться на интервью зарубежного компьютерного журнала о видеоиграх Edge с Джоном Кармаком после того как был анонсирован выход игры Doom на Atari Jaguar, но процесс разработки был еще в середине процесса.
Приведу лишь ссылки на скрины (т.к. они сами довольно большие по размеру):

i.imgur.com/rLUV4OZ.jpg
i.imgur.com/He5c9rd.jpg
i.imgur.com/zTcX50I.jpg
i.imgur.com/adZsajM.jpg

Если вкратце, то Кармак весьма нахваливал консоль и даже выразился о ней как о лучшей игровой платформе на тот момент времени.
По его словам у него заняло две недели от начала портирования Doom на Atari Jaguar прежде чем хоть какая то картинка на телевизоре появилась, но с ужасным фреймрейтом.
Он подтверждает, что основной процессор m68k слишком медленный, но дополнительные RISC-ядра — это вестчь! Но ему требуется время чтобы переписать код так, чтобы он помещался стадиями в маленькие кусочки памяти RISC-ядер (см. описание Atari Jaguar выше если еще не).
Причём сперва он любопытства ради начал портировать движок Wolf 3D со SNES на Atari Jaguar и когда «пятнадцатью сидиромов позднее» у него получилась картинка — он послал результат в Atari и они дали добро на порт Doom.
Но до этого Джон потратил три недели чтобы сделать лучший порт Вольфеншейна среди всех прочих — он работает на 30 фпс с вчетверо большей деталистичностью чем на ПК и даже звук звучит на 22 кГц, что в трое больше чем на ПК. В общем этим портом он остался доволен.
Но Doom на момент написания статьи всё еще представлялся тёмной лошадкой — Кармак говорит, что текстурирование будет выполнятся не совсем так же как на ПК, но по схожему принципу. Консоль весьма хвалит называя лучшим игровым железом на тот момент на рынке. Положительно отзывается о процессоре объектов, т.к. тот и картинку позволяет легко компоновать из разных сюрфейсов так и спрайты поверх выводить в совершенно свободном виде. Так же он хвалит модель цвета CRY (нечто вроде CMY(k), как я писал в статье) и вообще называет её лучшей в мире моделью цвета для видеоигр ибо затенение (освещение) становится тривиальной штукой (просто канал яркости это отдельный канал яркости). Ну а 16-битный цвет сам по себе должен был позволить выйти за рамки ограничений ПК-шной 256-цветной палитры намного и всерьёз.
Однако уже здесь Кармак признавал, что Jaguar не удастся добиться плавности в 30 фпс какую Doom имел на процессоре класса Pentium — тут он на тот момент разводил руками: «посмотрим как получится».
Здесь же он упоминает, что несмотря на то, что он сперва был недоволен тем, что Atari пытаются разработать собственные RISC-процессоры, но в итоге он нашёл их довольно быстрыми и приятными в разработке — единственный минус — малый объём локальной памяти. Ну и то, что в них есть баги (лол!).
Так что единственная аппаратная ошибка которую, по его мнению, совершила Atari — это то, что в качестве ЦП в консоли стоит m68k. RISC-ядра по его мнению в 20 раз быстрее.

Далее разговор немного отходит от консоли, но просто ради фана упомяну интересные моменты. В этот момент Кармак говорит, что в разработке находятся три игры на движке Doom: Doom II, некая Druid от Raven Software («фентезийная версия Doom») и Strife от Sygnus Studio. И что уже неиллюзорно пахнет Quake-ом.
Просто факты о том о сём: разработка графического ядра Wolf 3D заняла месяц, разработка графического ядра Doom заняла уже 3 месяца, но потом пришлось потратить 2 месяца на полное переписывание его под новый центральный алгоритм. Одним из наиболее трудоёмких алгоритмов к реализации в движке Doom он называет определение видимости по лучу в лабиринте карты, в то время как параллакс неба называет весьма простой штукой.
Ну и напоследок высказывается (как со стороны журналиста так и Кармака) пренебрежение к Full-Motion-Video играм (виртуальным тирам) и Кармак прямо говорит, что до тех пор пока Nintendo не прекратит бегать со своей ханженской моралью вряд ли что-то от id software появится еще на их консолях (отсылка к тому, что в Wolf3D пришлось убрать свастики).

P.S.

Ах, да. Doom на Atari Jaguar получился всё-таки мыльноватым, хотя фпс нормальный для того времени:

youtu.be/04Q_Jl7nGdM
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.