Urządzenie HardDoom ][™¶
Grafika w grze Doom 2¶
Rzutowanie dowolnej geometrii trójwymiarowej na dwuwymiarową płaszczyznę jest dość skomplikowane obliczeniowo. Jednym z ważniejszych elementów jest obliczenie współczynnika perspektywy dla każdego rysowanego piksela – wymaga to obliczenia odwrotności pierwiastka kwadratowego. Jest to bardzo kosztowna operacja i wykonanie jej dla każdego piksela ekranu jest niemożliwe przy zachowaniu rozsądnej ilości ramek na sekundę, nawet dla najnowocześniejszych i napotężniejszych procesorów i486, nie mówiąc już o procesorach i386 używanych obecnie przez większość graczy.
Gra Doom 2 zalicza się do tzw. gier 2.5D – choć grafika wygląda na trójwymiarową (i jest bardzo realistyczna), użyta geometria oraz punkt widzenia są bardzo ograniczone. Użytkownik może patrzeć tylko przed siebie (a nie w górę czy w dół), a w świecie gry spotkamy tylko 3 typy obiektów:
pionowe ściany – po zrzutowaniu na ekran, każda pokryta kolumna pikseli składa się z pikseli o równym współczynniku perspektywy, pozwalając na wyliczenie go tylko raz na każdą kolumnę.
poziome płaszczyzny (podłogi i sufity) – po zrzutowaniu na ekran, każda pokryta linia pikseli składa się z pikseli o równym współczynniku perspektywy.
obiekty ruchome, rysowane przez skopiowanie prosto na ekran przeskalowanych tzw. sprite’ów, czyli przygotowanych przez autorów zdjęć, zrobionych z 8 różnych kątów.
Główna praca rysowania świata gry spada na dwie gorące funkcje:
R_DrawColumn
– rysuje kolumnę pikseli z podanej kolumny tekstury i z podanym współczynnikiem skalowania. Używane do rysowania ścian, obiektów oraz grafiki interfejsu.R_DrawSpan
– rysuje poziomy pasek pikseli, teksturując podaną teksturą płaszczyzny (wycinając z tej tekstury linię pod dowolnym kątem i nakładając ją na rysowany pasek).
Urządzenie HardDoom ][™ dostarcza sprzętową implementację powyższych funkcji, przejmując większość obciążenia z głównego procesora i pozwalając na grę w wysokich rozdzielczościach (płynna rozgrywka na 640×480!) nawet na starszych procesorach. Oprócz tych funkcji, urządzenie dostarcza również kilka pomniejszych funkcji pomocniczych, pozwalając na rysowanie całej grafiki gry na urządzeniu.
Urządzenie¶
Urządzenie jest podłączane do komputera przez szynę PCI –
identyfikator producenta to 0x0666
, a identyfikator urządzenia to
0x1994
.
Urządzenie nie posiada własnej pamięci i operuje na buforach w głównej pamięci komputera przez bezpośredni dostęp do pamięci (DMA). Ponieważ główna pamięć komputera podlega fragmentacji, a bufory mogą być całkiem duże (urządzenie obsługuje 2048×2048 pikseli), urządzenie wykonuje dostęp do większości buforów przez tablicę stron w swoim własnym formacie.
Urządzeniem steruje się przez rejestry wejścia/wyjścia zmapowane do pamięci (MMIO). Ten obszar MMIO jest pierwszym i jedynym obszarem BAR używanym przez urządzenie (BAR0). Urządzenie wykorzystuje również jedną linię przerwania PCI.
Obszar MMIO ma wielkość 8kiB, ale tylko niektóre bajty z tego zakresu są używane na rejestry. Wszystkie udokumentowane rejestry są 32-bitowe w formacie little-endian i powinny być używane tylko przez wyrównane 32-bitowe odczyty i zapisy.
Bufory i blok stronicowania¶
Urządzenie używa następujących buforów (opisanych bardziej szczegółowo niżej):
bufor poleceń – zmiennego rozmiaru.
bufory ramki (“surface”) – zmiennego rozmiaru.
atlas tekstur kolumnowych (“texture”) – zmiennego rozmiaru.
atlas tekstur płaskich (“flat”) – zmiennego rozmiaru, wielokrotność 2**12 bajtów.
atlas map kolorów (“colormap”) – zmiennego rozmiaru, wielokrotność 2**8 bajtów.
mapa przezroczystości (“tranmap”) – zawsze rozmiaru 2**16 bajtów.
Urządzenie pisze tylko do bufora ramki – pozostałe bufory są używane tylko do odczytu.
Bufory wybiera się przez podanie adresu ich tabeli stron. W każdej chwili wybrane jest 8 buforów:
CMD
: bufor poleceń, z którego urządzenie wczytuje polecenia.SURF_DST
: bufor ramki, do którego urządzenie będzie rysować.SURF_SRC
: bufor ramki, z którego urządzenie będzie kopiować dane (dla poleceniaCOPY_RECT
).TEXTURE
: atlas tekstur kolumnowych, z których urządzenie będzie rysować (dla poleceniaDRAW_COLUMN
).FLAT
: atlas tekstur płaskich, z których urządzenie będzie rysować (dla poleceńDRAW_BACKGROUND
,DRAW_SPAN
).COLORMAP
: atlas map kolorów do oświetlenia i efektów specjalnych.TRANSLATION
: atlas map kolorów do zmiany palety kolorów.TRANMAP
: mapa przezroczystości.
Urządzenie używa 40-bitowych adresów fizycznych (zarówno dla buforów jak i dla tabel stron).
Wybrany bufor poleceń ustawia się przez zapis rejestru CMD_PT
. Pozostałe
bufory ustawia się przez wysłanie polecenia SETUP
. W każdym wypadku,
wybrany bufor podaje się jako 32-bitową wartość, która jest przesuniętym
wskaźnikiem adresu tabeli stron bufora (bity 8-39 adresu fizycznego tabeli
stron to podana wartość, pozostałe bity adresu są zerami).
Urządzenie używa stron o wielkości 4kiB. Tabele stron mogą zawierać maksymalnie 1024 wpisy (czyli opisywać 4MiB pamięci – maksymalny rozmiar bufora) i muszą być wyrównane do 256 bajtów. Wpisy tabeli stron mają 4 bajty i odpowiadają bezpośrednio kolejnym stronom bufora. Wpisy tabeli stron są 32-bitowymi słowami o następującym formacie:
bit 0:
VALID
– jeśli ustawiony, wpis jest poprawny i może być użyty. Jeśli nie jest ustawiony, próba użycia wpisu spowoduje błądPAGE_FAULT
i wyłączenie odpowiedniego bloku wENABLE
(XY
dlaSURF_*
,TEX
dlaTEXTURE
). [XXX:FE
]bit 1:
WRITABLE
– jeśli ustawiony, ta strona jest dostępna do odczytu i zapisu. Jeśli nie jest ustawiony, ta strona jest dostępna tylko do odczytu, a próba zapisu spowoduje błądPAGE_FAULT
i wyłączenie odpowiedniego bloku wENABLE
.bity 2-3: nieużywane, powinny być równe 0.
bity 4-31:
ADDR
– bity 12-39 adresu fizycznego strony.
Rozmiar tabeli stron nie jest nigdzie podawany – urządzenie w żaden sposób nie sprawdza, czy użyty offset w buforze zmieści się w tabeli stron. Sterownik powinien zapewnić, że tabela będzie odpowiednio duża i pilnować wysyłanych poleceń, czyli:
weryfikować, że wysyłane współrzędne y mieszczą się w wysokości buforów ramek,
limitować odczyt tekseli z tekstur kolumnowych przez użycie
TEXTURE_LIMIT
,weryfikować, że
FLAT_IDX
,COLORMAP_IDX
,TRANSLATION_IDX
mieszczą się w rozmiarze odpowiednich atlasów.
Aby nie czytać ciągle tabeli stron, urządzenie może zapamiętywać
dane z tabeli stron w buforach TLB. Zmiana aktywnego bufora (przez polecenie
SETUP
bądź zapis CMD_PT
)
czyści bufory TLB odpowiadające danemu buforowi, a użycie bitu
TLB
w rejestrze RESET
czyści wszystkie bufory TLB.
W razie wystąpienia błędu PAGE_FAULT
, urządzenie można zrestartować
przez wpisanie odpowiedniej wartości w tabelę stron, skasowanie TLB,
oraz włączenie z powrotem odpowiedniego bloku w ENABLE
– kontynuuje
wtedy pracę od momentu w którym trafiło na błąd strony.
Bufory ramek¶
Bufor ramki to obszar w pamięci służący do rysowania. Jest to po prostu
dwuwymiarowa tablicą pikseli. Ponieważ urządzenie było projektowane zanim
wynaleziono kolor 24-bitowy (albo nawet 16-bitowy), każdy piksel jest po
prostu bajtem – odpowiadającym jakiemuś kolorowi z palety (obsługą palety
zajmuje się urządzenie wyświetlające i nie musimy się nią przejmować).
Urządzenie obsługuje bufory ramki o dowolnej dodatniej szerokości
podzielnej przez 64 i nie większej niż 2048 piksele. Wysokość natomiast
może być dowolna z zakresu 1 .. 2048. Bufor ramki jest prostą tablicą
bajtów – adres piksela (x, y) wewnątrz bufora to po prostu x + y * width
.
Szerokość aktywnych buforów ramki jest ustawiana poleceniem SETUP
.
Urządzenie sprawdza współrzędną x pikseli, których używa – przekroczenie
szerokości bufora spowoduje błąd SURF_DST_OVERFLOW
lub
SURF_SRC_OVERFLOW
i wyłączenie bloku XY
w ENABLE
.
Tekstury kolumnowe¶
Tekstury kolumnowe zawierają dane obrazu, który polecenie DRAW_COLUMN
będzie rysowało do bufora ramki (po przeskalowaniu i przetworzeniu).
Mają dość skomplikowany format i składają z tekseli pogrupowanych
w kolumny (które nie muszą pokrywać całej powierzchni tekstury
– tekstury kolumnowe mogą mieć dziury). Urządzenie nie przejmuje się
dokładnym formatem tych tekstur – znalezienie w nim początku odpowiedniej
kolumny jest zadaniem silnika gry. Tekstury kolumnowe mogą mieć dość dowolny
rozmiar (w praktyce od kilkudziesięciu bajtów do kilkudziesięciu kilobajtów,
zazwyczaj ok. 2 kiB) i mogą być grupowane w atlasy (bufory zawierające wiele
tekstur). Urządzenie obsługuje atlasy o wielkościach do 4MiB.
Aktywny atlas tekstur kolumnowych ustawia się poleceniem SETUP
.
Aktywną teksturę (a właściwie kolumnę z tekstury) wybiera się przy wysyłaniu
polecenia DRAW_COLUMN
przez podanie parametrów TEXTURE_OFFSET
,
TEXTURE_HEIGHT
i TEXTURE_LIMIT
.
Wysokość jest używana do powtarzania tekstury w pionie
– współrzędne w kolumnie tekstury będą brane modulo wysokość.
Próba czytania adresu z poza zakresu 0 .. TEXTURE_LIMIT << 6 | 0x3f
zostanie
zablokowana przez urządzenie i spowoduje użycie do teksturowania tekseli
zerowych.
Urządzenie może zapamiętywać dane z używanego atlasu tekstur w swojej
pamięci podręcznej – aby wyczyścić tą pamięć, wystarczy zmienić aktywny
atlas przez wysłanie polecenia SETUP
z flagą TEXTURE
(to zresetuje pamięć podręczną nawet, jeśli nie zmieni
się przez to adres aktywnej tabeli stron).
Note
Aby nie mylić pojęć z odpowiadającymi pojęciami w buforach ramki, w grafice komputerowej przyjęło się nazywać współrzędne w teksturze U oraz V (zamiast X i Y), a pojedynczy element – tekselem (zamiast piksela).
Tekstury płaskie¶
Tekstury płaskie są używane przez polecenie DRAW_SPAN
do rysowania
podłóg i sufitów. Mają zawsze wymiary 64×64 tekseli, zajmują 2**12
bajtów, a ich adres początkowy musi być wyrównany do 2**12 bajtów.
Podobnie do tekstur kolumnowych, mogą być grupowane w atlasy
tekstur płaskich.
Aktywny atlas tekstur płaskich ustawia się poleceniem SETUP
z flagą
FLAT
. Aktywną teksturę wybiera sie przy wysyłaniu polecenia DRAW_SPAN
bądź DRAW_BACKGROUND
przez parametr FLAT_IDX
(wybrana tekstura płaska
jest pod adresem FLAT_IDX * 2 ** 12
wewnątrz bufora).
Analogicznie do tekstury kolumnowej, urządzenie może zapamiętywać dane
z tekstury płaskiej w pamięci podręcznej. Wysłanie polecenia SETUP
z flagą FLAT
czyści tą pamięć.
Mapy kolorów¶
Mapy kolorów są po prostu tablicami mapującymi kolory z palety na inne kolory – mają przez to zawsze dokładnie 256 bajtów. Ich adres musi być również wyrównany do 256 bajtów. Są używane do wielu efektów:
zamiana palety kolorów, aby umożliwić użycie tej samej tekstury do kilku wersji kolorystycznych (tzw. palette swap) – w końcu pamięć jest droga
ściemnianie kolorów (do symulacji słabego oświetlenia)
zmiana skali kolorów (np. przefarbowanie wszystkiego na niebiesko pod wodą)
Urządzenie ma dwa aktywne atlasy map kolorów, wybierane poleceniem SETUP
z flagami COLORMAP
i TRANSLATION
. Aktywną mapę kolorów można wybrać
dla każdego polecenia przez podanie indeksu w odpowiednim atlasie (wybrana
mapa kolorów znajduje się pod adresem indeks * 256
w odpowienim buforze).
Podobnie do tekstur, urządzenie może kopiować dane map
do pamięci podręcznej. Wysłanie polecenia SETUP
z flagą COLORMAP
bądż TRANSLATION
czyści zawartość odpowiadającej pamięci.
Ustawione mapy kolorów są używane przez polecenia DRAW_COLUMN
i DRAW_SPAN
tylko wtedy, gdy ustawione są odpowiednie flagi – COLORMAP
dla
mapy COLORMAP_*
, TRANSLATION
dla mapy TRANSLATION_*
. Polecenie
DRAW_FUZZ
zawsze używa mapy COLORMAP_*
do efektu cienia.
Mapy przezroczystości¶
Aby uzyskać efekt przezroczystości w grafice komputerowej, potrzebna jest jakaś funkcja scalająca dwa kolory – kolor tła oraz kolor rysowanego obiektu. W przypadku grafiki używającej schematu True Color, wystarczyłoby zsumować składowe kolorów z odpowiednimi wagami. Jednak w przypadku grafiki używającej palety kolorów, trzeba to zrobić używając obliczonej wcześniej tabeli – mapy przezroczystości. Mapa przezroczystości jest dwuwymiarową tablicą bajtów o rozmiarze 256×256. Jest to po prostu tablica mapująca pary kolorów na scalony kolor.
Urządzenie ma jedną aktywną mapę przezroczystości, wybieraną poleceniem SETUP
z flagą TRANMAP
. Znajduje się ona pod adresem 0 w wybranym buforze.
Podobnie do tekstur i map kolorów, dane z mapy kolorów mogą być przechowywane przez urządzenie w pamięci podręcznej.
Wysyłanie poleceń¶
Urządzenie sterowane jest w większości przez wysyłanie mu poleceń. Każde
polecenie jest pakietem złożonym z ośmiu 32-bitowych słów.
Polecenia mogą być wysyłane bezpośrednio przez rejestry MMIO (jest to mniej
wydajna opcja), bądź przez wskazanie bufora w pamięci, z którego urządzenie
powinno wczytywać polecenia (bardziej wydajna opcja). W przypadku wysłania
niepoprawnego polecenia, wyzwalane jest przerwanie FE_ERROR
, a blok
FE
zostanie wyłączony w rejestrze ENABLE
.
Urządzenie obsługuje 8 różnych poleceń:
0
:COPY_RECT
– kopiuje prostokątny obszar między dwoma buforami ramki.1
:FILL_RECT
– wypełnia prostokątny obszar jednym kolorem.2
:DRAW_LINE
– rysuje prostą jednokolorową linię między dwoma punktami.3
:DRAW_BACKGROUND
– rysuje tło – wypełnia prostokątny obszar powtarzaną w nieskończoność teksturą płaską.4
:DRAW_COLUMN
– rysuje kolumnę pikseli używając tekstury kolumnowej.5
:DRAW_FUZZ
– aplikuje efekt rozmytego cienia na kolumnie pikseli.6
:DRAW_SPAN
– rysuje pasek pikseli używając tekstury płaskiej.7
:SETUP
– zmiena bufory używane przez urządzenie.
Urządzenie przyjmuje polecenia w jednym z dwóch formatów. Format pierwszy jest używany
dla wszystkich poleceń poza SETUP
i wygląda następująco:
słowo 0:
bity 0-3:
CMD_TYPE
– typ polecenia (z powyższej listy).bit 4:
INTERLOCK
– zapewnia zakończenie wszystkich wcześniejeszych poleceń przed rozpoczęciem wczytywania danych dla tego polecenia (i wszystkich późniejszych).bit 5:
PING_ASYNC
– wyzwala przerwanie po wczytaniu tego polecenia.bit 6:
PING_SYNC
– wyzwala przerwanie po zakończeniu przetwarzania tego polecenia.bit 7:
FENCE
– zwiększa licznikFENCE_COUNTER
po zakończeniu przetwarzania tego polecenia (i wszystkich wcześniejszych).bit 8:
TRANSLATION
– włącza zamianę palety kolorów. Jeśli włączony, kolory z tekstury są tłumaczone przez mapę kolorów zTRANSLATION_IDX
.bit 9:
COLORMAP
– włącza mapowanie rysowanych kolorów. Jeśli włączony, kolory z tekstury są tłumaczone przez mapę kolorów zCOLORMAP_IDX
(poTRANSLATION_IDX
, jeśli obydwie mapy są włączone).bit 10:
TRANMAP
– włącza przezroczystość. Jeśli włączony, rysowane kolory są scalane z obecnymi kolorami w buforze ramki przez mapę przezroczystości (TRANMAP_PT
).
słowo 1:
bity 0-13:
TRANSLATION_IDX
– indeks użytej mapy kolorów dla zmiany palety wDRAW_COLUMN
iDRAW_SPAN
. Użyta mapa kolorów pochodzi z adresuTRANSLATION_IDX * 2**8
wewnątrz bufora wyznaczonego przezTRANSLATION_PT
bity 16-29:
COLORMAP_IDX
– indeks użytej mapy kolorów dla oświetlenia i efektów dlaDRAW_COLUMN
,DRAW_SPAN
, orazDRAW_FUZZ
. Użyta mapa kolorów pochodzi z adresuCOLORMAP_IDX * 2**8
wewnątrz bufora wyznaczonego przezCOLORMAP_PT
słowo 2:
bity 0-10:
X_A
– współrzędna x pierwszego punktu będącego parametrem operacji (interepretacja zależy od konkretnego polecenia, nie wszystkie polecenia tego używają).bity 11-21:
Y_A
– współrzędna y pierwszego punktu będącego parametrem operacji.bity 22-31:
FLAT_IDX
– indeks użytej tekstury płaskiej w aktywnym atlasie tekstur płaskich (dlaDRAW_BACKGROUND
,DRAW_SPAN
).
słowo 3:
bity 0-10:
X_B
– współrzędna x drugiego punktu będącego parametrem operacji.bity 11-21:
Y_B
– współrzędna y drugiego punktu będącego parametrem operacji.
słowo 4:
USTART
– współrzędna u w teksturze używana dla skrajnie lewego piksela paska (dlaDRAW_SPAN
) bądź górnego piksela kolumny (dlaDRAW_COLUMN
). Jest to liczba stałoprzecinkowa – 16 wysokich bitów to część całkowita, a 16 niskich to część ułamkowa.słowo 5:
USTEP
– pochodna współrzędnej u w teksturze względem współrzędnej x lub y w buforze ramki. Liczba stałoprzecinkowa ze znakiem.słowo 6:
dla poleceń
COPY_RECT
,FILL_RECT
,DRAW_LINE
,DRAW_BACKGROUND
:bity 0-11:
WIDTH
– szerokość prostokąta (dlaCOPY_RECT
,FILL_RECT
,DRAW_BACKGROUND
).bity 12-23:
HEIGHT
– wysokość prostokąta.bity 24-31:
FILL_COLOR
– kolor wypełnienia dlaFILL_RECT
, kolor linii dlaDRAW_LINE
.
dla polecenia
DRAW_COLUMN
:bity 0-21:
TEXTURE_OFFSET
– offset początku danych kolumny w aktywnym atlasie tekstur kolumnowych w bajtach.
dla polecenia
DRAW_SPAN
:VSTART
– współrzędna v w teksturze używana dla skrajnie lewego piksela paska (dlaDRAW_SPAN
). Również liczba stałoprzecinkowa.dla polecenia
DRAW_FUZZ
:bity 0-10:
FUZZ_START
– współrzędna y początku pola widzenia.bity 12-22:
FUZZ_END
– współrzędna y końca pola widzenia.bity 24-29:
FUZZ_POS
– źródło losowości dla efektu cienia.
słowo 7:
dla polecenia
DRAW_COLUMN
:bity 0-15:
TEXTURE_LIMIT
– określa ostatni poprawny adres w teksturze kolumnowej, liczony w 64-bajtowych blokach (adres ostatniego poprawnego bajtu toTEXTURE_LIMIT << 6 | 0x3f
).bity 16-31:
TEXTURE_HEIGHT
– wysokość tekstury w tekselach, jeśli tekstura ma być powtarzana w pionie (współrzędne w kolumnie tekstury będą brane modulo wysokość) bądź 0, jeśli tekstura nie ma być powtarzana.
dla polecenia
DRAW_SPAN
:VSTEP
– pochodna współrzędnej u w teksturze względem współrzędnej x lub y w buforze ramki. Liczba stałoprzecinkowa ze znakiem.dla pozostałych poleceń: nieużywane.
Format drugi jest używany dla polecenia SETUP
i jest opisany razem z nim.
Wszystkie nieużywane pola (czy to kompletnie niezdefiniowane, czy nie stosujące się dla danego typu polecenia) muszą być ustawione na 0 – w przeciwnym wypadku, zachowanie urządzenia nie jest zdefiniowane.
Bezpośredni dostęp¶
Polecenia można wysyłać do urządzenia bezpośrednio przez MMIO, używając następujących rejestrów:
BAR0 + 0x0070: CMD_FREE
Rejestr tylko do odczytu. Odczytana wartość jest liczbą wolnych miejsc w kolejce poleceń (tyle poleceń można natychmiast zapisać do
CMD_SEND
bez obaw oCMD_OVERFLOW
). Kolejka ta ma maksymalną pojemność 512 poleceń.BAR0 + 0x0040 + i * 4, i < 8: CMD_SEND
Rejestry tylko do zapisu. Można wysłać polecenie do urządzenia, zapisując jego kolejne słowa do kolejnych rejestrów z tej tablicy (i-te słowo do i-tego rejestru, w kolejności). Zapis ostatniego słowa powoduje dopisanie zapisanego polecenia na koniec kolejki poleceń. Jeśli kolejka jest już pełna (
CMD_FREE == 0
), zamiast tego wyzwalane jest przerwanieCMD_OVERFLOW
, a blokCMD_SEND
jest wyłączany wENABLE
.
Blok wczytywania poleceń¶
Blok wczytywania poleceń pozwala na efektywne sterowanie urządzeniem (bez konieczności ręcznego wysyłania każdego polecenia przez MMIO) przez samodzielne wczytywanie poleceń z pamięci. Rejestry bloku wczytywania poleceń sa następujące:
BAR0 + 0x0060: CMD_PT
Wskaźnik na tabelę stron opisującą bufor poleceń, przesunięty w prawo o 8 bitów (rejestr przechowuje bity 8-39 adresu fizycznego). Zapis tego rejestru powoduje spłukanie bufora TLB dotyczącego bufora poleceń.
BAR0 + 0x0064: CMD_SIZE
Rozmiar bufora poleceń, liczony w poleceniach (czyli w 32-bajtowych pakietach). Gdy urządzenie zwiększa
CMD_READ_IDX
, a obecną wartością jestCMD_SIZE-1
, zachodzi zawinięcie bufora i nową wartością będzie0
.BAR0 + 0x0068: CMD_READ_IDX
Indeks następnego polecenie do wczytania (liczony w 32-bajtowych pakietach).
BAR0 + 0x006c: CMD_WRITE_IDX
Indeks miejsca, gdzie procesor ma zapisać następne polecenie. Jeśli
CMD_WRITE_IDX == CMD_READ_IDX
, blok wczytywania poleceń zostanie zatrzymany, aż procesor załaduje więcej poleceń i przesunieCMD_WRITE_IDX
.
Blok wczytywania poleceń będzie wczytywał polecenia zawsze, gdy zachodzą wszystkie z następujących warunków:
blok wczytywania poleceń jest włączony w
ENABLE
są jakieś nieprzetworzone polecenia, tzn.
CMD_READ_IDX != CMD_WRITE_IDX
jest miejsce w kolejce poleceń, tzn.
CMD_FREE != 0
Polecenie wczytywane jest z indeksu CMD_READ_IDX
, jest on zwiększany o 1
(ewentualnie jest zawijany do 0, jesli wynosi obecnie CMD_SIZE-1
),
po czym polecenie jest dopisywane do kolejki (tak, jakby zostało wpisane do CMD_SEND
).
Warning
Po resecie urządzenia, CMD_READ_IDX
nie musi być równe CMD_WRITE_IDX
–
blok wczytywania poleceń może więc próbować wczytać jakieś polecenia po
włączeniu go w ENABLE
. Aby tego uniknąć, należy zainicjować te rejestry.
Opis poleceń¶
Polecenie SETUP
¶
Polecenie SETUP
służy do zmiany aktywnych buforów. Ma specjalny format,
inny od pozostałych poleceń:
słowo 0:
bity 0-3:
CMD_TYPE
– typ polecenia (z powyższej listy).bit 4:
INTERLOCK
– zapewnia zakończenie wszystkich wcześniejeszych poleceń przed rozpoczęciem wczytywania danych dla tego polecenia (i wszystkich późniejszych).bit 5:
PING_ASYNC
– wyzwala przerwanie po wczytaniu tego polecenia.bit 6:
PING_SYNC
– wyzwala przerwanie po zakończeniu przetwarzania tego polecenia.bit 7:
FENCE
– zwiększa licznikFENCE_COUNTER
po zakończeniu przetwarzania tego polecenia (i wszystkich wcześniejszych).bit 9:
SURF_DST
– zmienia aktywny docelowy bufor ramki.bit 10:
SURF_SRC
– zmienia aktywny źródłowy bufor ramki.bit 11:
TEXTURE
– zmienia aktywną teksturę kolumnową.bit 12:
FLAT
– zmienia aktywną teksturę płaską.bit 13:
TRANSLATION
– zmienia aktywny atlas map kolorów do zmiany palety.bit 14:
COLORMAP
– zmienia aktywny atlas map kolorów do efektów i oświetlenia.bit 15:
TRANMAP
– zmienia aktywną mapę przezroczystości.bity 16-21:
SURF_DST_WIDTH
– bity 6-11 szerokości ramki docelowej (bity 0-5 szerokości są równe 0). Ignorowane, jeśli nie jest ustawiony bitSURF_DST
.bity 24-29:
SURF_SRC_WIDTH
– bity 6-11 szerokości ramki źródłowej (bity 0-5 szerokości są równe 0). Ignorowane, jeśli nie jest ustawiony bitSURF_SRC
.
słowo 1:
SURF_DST_PT
: bity 8-39 adresu tabeli stron opisującej docelowy bufor ramki. Ignorowane, jeśli nie jest ustawiony bitSURF_DST
.słowo 2:
SURF_SRC_PT
: jak wyżej, źródłowy bufor ramki.słowo 3:
TEXTURE_PT
: jak wyżej, bufor tekstury kolumnowej.słowo 4:
FLAT_PT
: jak wyżej, bufor tekstury płaskiej.słowo 5:
TRANSLATION_PT
: jak wyżej, atlas map kolorów do zmiany palety.słowo 6:
COLORMAP_PT
: jak wyżej, atlas map kolorów do efektów i oświetlenia.słowo 7:
TRANMAP_PT
: jak wyżej, mapa przezroczystości.
Jednym poleceniem SETUP
można zmienić dowolny podzbiór ustawień (wybrany przez bity w słowie 0).
Będą one obowiązywały aż do zmiany ich przez kolejne polecenie SETUP
.
Wykonanie tego polecenia resetuje jednocześnie bufory TLB dla wszystkich buforów wybranych w słowie 0 (nawet, jeśli wybrany adres tabeli stron jest identyczny z wcześniej obowiązującym). Analogicznie, dla wybranych buforów czyszczona jest pamięć podręczna.
Polecenie COPY_RECT
¶
Polega na skopiowaniu zadanego prostokąta z jednego
bufora ramki (SURF_SRC_PT
) do drugiego (SURF_DST_PT
). Obydwa
bufory ramki muszą być tych samych rozmiarów.
Jego parametry to:
pozycja lewego górnego rogu prostokąta docelowego (
X_A
,Y_A
),pozycja lewego górnego rogu prostokąta źródłówego (
X_B
,Y_B
),wymiary prostokąta (
WIDTH
,HEIGHT
).
Polecenie COPY_RECT
nie powinno być wykonywane, gdy kopiujemy wewnątrz
jednego bufora, a prostokąt źródłowy ma część wspólną z prostokątem docelowym
– wynik jest wtedy niedeterministyczny.
Warning
Urządzenie może wczytywać dane źródłowe dla COPY_RECT
asynchronicznie
do procesu rysowania.
Aby zapewnić, że urządzenie zakończyło wcześniejesze operacje rysowania do
źródłowego prostokąta zanim zacznie z niego czytać, należy ustawić flagę
INTERLOCK
(opisane niżej).
Polecenie jest używane w grze do skopiowania przygotowanego wcześniej panelu dolnego oraz do efektu przejścia (“melt”).
Polecenie FILL_RECT
¶
Polega na wypełnieniu zadanego prostokąta w buforze ramki (SURF_DST_PT
)
jednym kolorem. Jego parametry to:
pozycja lewego górnego rogu prostokąta (
X_A
,Y_A
),wymiary prostokąta (
WIDTH
,HEIGHT
),kolor (
FILL_COLOR
).
Jest używane w grze do rysowania tła mapy (dostępnej pod klawiszem Tab).
Polecenie DRAW_LINE
¶
Rysuje jednokolorową linię prostą o szerokości 1 piksela między podanymi
dwoma punktami w zadanym buforze ramki (SURF_DST_PT
).
Jego parametry to:
pozycja punktu początkowego (
X_A
,Y_A
),pozycja punktu końcowego (
X_B
,Y_B
),kolor (
FILL_COLOR
).
Jest używane w grze do rysowania mapy (dostępnej pod klawiszem Tab).
Polecenie DRAW_BACKGROUND
¶
Wypełnia zadany prostokąt w buforze ramki (SURF_DST_PT
) powtarzającymi się kopiami
tekstury płaskiej (FLAT_PT
). Jego parametry to:
pozycja lewego górnego rogu prostokąta (
X_A
,Y_A
),wymiary prostokąta (
WIDTH
,HEIGHT
),
Jest używane w grze do rysowania tła do ekranu opcji, tła do tekstu “fabuły” wyświetlanego po ukończeniu niektórych poziomów, oraz jako obramowanie ekranu w przypadku wybrania pola widzenia mniejszego niż ekran (klawisz -).
Polecenie DRAW_COLUMN
¶
Rysuje teksturowaną kolumnę do bufora ramki (SURF_DST_PT
).
Jego parametry to:
współrzędne górnego punktu kolumny (
X_A
,Y_A
),współrzędne dolnego punktu kolumny (
X_B
,Y_B
),flagi
TRANSLATION
,COLORMAP
,TRANMAP
,wartość początkowa współrzędnej u w teksturze (
USTART
),pochodna współrzędnej u po współrzędnej y (
USTEP
),offset początku danych kolumny w teksturze kolumnowej (
TEXTURE_OFFSET
),mapa kolorów do efektów i oświetlenia (
COLORMAP_IDX
) – jeśli ustawiona jest flagaCOLORMAP
,mapa kolorów do zmiany palety (
TRANSLATION_IDX
– jeśli ustawiona jest flagaTRANSLATION
.
Polecenie rysuje kolumnę pikseli do bufora ramki na
współrzędnych X_A, Y_A
do X_B, Y_B
. X_A
powinno
być równe X_B
, a Y_A
powinno być mniejsze od lub równe Y_B
(inaczej zachowanie urządzenia jest niezdefiniowane).
Rysowana kolumna jest teksturowana za pomocą następującego algorytmu:
# Obliczenie koloru dla piksela (x, y).
coord = (USTART + USTEP * (y - Y_A)) >> 16
if TEXTURE_DIMS.HEIGHT != 0:
coord %= TEXTURE_HEIGHT
tex_offset = TEXTURE_OFFSET + coord
if tex_offset < 0 or (tex_offset >> 6) > TEXTURE_LIMIT:
color = 0;
else:
color = read_paged(TEXTURE_PT, tex_offset)
if TRANSLATION:
color = read_paged(TRANSLATION_PT, TRANSLATION_IDX << 8 | color)
if COLORMAP:
color = read_paged(COLOR_PT, COLOR_IDX << 8 | color)
if TRANMAP:
bg_color = surf_read(SURF_DST_PT, x, y);
color = read_paged(TRANMAP_PT, bg_color << 8 | color)
Polecenie DRAW_FUZZ
¶
Aplikuje efekt rozmytego cienia na kolumnie w buforze ramki (SURF_DST_PT
).
Jego parametry to:
współrzędne górnego punktu kolumny (
X_A
,Y_A
),współrzędne dolnego punktu kolumny (
X_B
,Y_B
),mapa kolorów do efektu cienia (
COLORMAP_IDX
),początkowa współrzędna y pola widzenia (
FUZZ_START
) – potrzebna, by efekt rozmycia nie użył pikseli z poza rysowanego obszaru ramki,końcowa współrzędna y pola widzenia (
FUZZ_END
),źródło losowości dla efektu cienia (
FUZZ_POS
) – liczba z zakresu 0-55,
Polecenie modyfikuje kolumnę pikseli w buforze ramki na
współrzędnych X_A, Y_A
do X_B, Y_B
. X_A
powinno
być równe X_B
, a współrzędnie y powinny spełniać nierówność FUZZ_START ≤ Y_A ≤ Y_B ≤ FUZZ_END
(inaczej zachowanie urządzenia jest niezdefiniowane). Urządzenie może przeczytać piksele
z wybranej kolumny o współrzędnych y z zakresu [FUZZ_START, FUZZ_END]
.
Polecenie DRAW_SPAN
¶
Rysuje teksturowany pasek do bufora ramki (SURF_DST_PT
).
Jego parametry to:
współrzędne lewego punktu paska (
X_A
,Y_A
),współrzędne prawego punktu paska (
X_B
,Y_B
),flagi
TRANSLATE
,COLORMAP
,TRANMAP
wartość początkowa współrzędnych u i v w teksturze (
USTART
,VSTART
),pochodna współrzędnych u i v po współrzędnej x (
USTEP
,VSTEP
),mapa kolorów do efektów i oświetlenia (
COLORMAP_IDX
) – jeśli ustawiona jest flagaCOLORMAP
,mapa kolorów do zmiany palety (
TRANSLATION_IDX
– jeśli ustawiona jest flagaTRANSLATE
.
Polecenie rysuje pasek pikseli do bufora ramki na
współrzędnych X_A, Y_A
do X_B, Y_B
. Y_A
powinno
być równe Y_B
, a X_A
powinno być mniejsze od lub równe X_B
(inaczej zachowanie urządzenia jest niezdefiniowane).
Rysowany pasek jest teksturowany za pomocą następującego algorytmu:
# Obliczenie koloru dla piksela (x, y).
u = (USTART + USTEP * (x - X_A)) >> 16 & 0x3f
v = (VSTART + VSTEP * (x - X_A)) >> 16 & 0x3f
color = read_paged(FLAT_PT, u | v << 6)
if TRANSLATE:
color = read_paged(TRANSLATION_PT, TRANSLATION_IDX << 8 | color)
if COLORMAP:
color = read_paged(COLOR_PT, COLOR_IDX << 8 | color)
if TRANMAP:
bg_color = surf_read(SURF_DST_PT, x, y);
color = read_paged(TRANMAP_PT, bg_color << 8 | color)
Synchronizacja¶
Blok rysujący działa wysoce asynchronicznie i równolegle. W szczególności, urządzenie może:
wczytywać nowe polecenia przed zakończeniem wykonania poprzednich.
wczytywać dane źródłowe dla polecenia przed zakończeniem wykonywania poprzednich poleceń (należy na to uważać przy operacji
COPY_RECT
!).rozpocząć rysowanie pikseli dla nowej operacji przed zakończeniem poprzedniej operacji (ale tylko, jeśli operacje te operują na rozłącznych pikselach w buforze ramki).
opóźnić rozpoczęcie wykonywania operacji do momentu wysłania kolejnych poleceń (aby spróbować połączyć je w większą paczkę wewnętrznych operacji).
Mamy jednak następujące gwarancje:
każde polecenie będzie używało stanu parametrów (adresów i rozmiarów buforów) z momentu jego rozpoczęcia.
jeśli wyślemy polecenie resetujące pamięć podręczną bądź bufor TLB, każde polecenie wysłane później będzie widziało dane wczytane już po wykonaniu tego resetu.
dla konkretnego piksela w docelowym buforze ramki, polecenia będą wykonywane zgodnie z kolejnością wysyłania (czyli wygra ostatni zapis).
polecenie
COPY_RECT
wczyta wszystkie swoje dane źródłowe przed rozpoczęciem rysowania późniejszych poleceń.urządzenie nie może mieć więcej niż 2048 poleceń w locie (wczytanych do FIFO, ale jeszcze nie wykonanych) – dopóki nasz bufor poleceń jest mniejszy niż
2**32 - 2048
, nie musimy się przejmować, że skończą nam się wolne identyfikatory doFENCE_COUNTER
.wysłanie polecenia z flagą
FENCE
bądźPING_SYNC
spowoduje wykonanie go w skończonym czasie (bez tych flag, mikrokod może oczekiwać na kolejne polecenia, by spróbować połączyć je w większe paczki).
Flaga INTERLOCK
¶
W praktyce, wykonanie przez urządzenie daje efekty identyczne do wykonania sekwencyjnego, z jednym
ważnym wyjątkiem – polecenie COPY_RECT
może wczytać piksele danego
bufora ramki zanim poprzednie polecenia zdążą je zapisać. Aby uniknąć
tego problemu, należy wykryć taką możliwość w sterowniku
i użyć flagi INTERLOCK
w poleceniu. Flaga INTERLOCK
blokuje rozpoczęcie wczytywania danych przez obecne i późniejsze polecenia
COPY_RECT
do momentu pełnego zakończenia wcześniejszych operacji
rysujących.
Aby wszystko działało poprawnie, wystarczy zapewnić, że między operacją
rysowania do danego bufora a operacją COPY_RECT
czytającą z niego
znajdzie się co najmniej jedno polecenie z ustawioną flagą INTERLOCK
.
Flagi PING_SYNC
i PING_ASYNC
¶
W każdym poleceniu możemy ustawić flagi PING_SYNC
oraz PING_ASYNC
.
Jeśli ustawiona jest flaga PING_SYNC
, urządzenie wyzwoli przerwanie
PONG_SYNC
po pełnym zakończeniu wykonywania danego polecenia. Jeśli
ustawiona jest flaga PING_ASYNC
, urządzenie wyzwoli przerwanie
PONG_ASYNC
gdy tylko polecenie zostanie wczytane z kolejki i zacznie
się wykonywać.
Licznik poleceń¶
Do elastycznego oczekiwania na wykonanie operacji przez urządzenie służy licznik poleceń, dostępny w następujących rejestrach MMIO:
BAR0 + 0x0010: FENCE_COUNTER
Rejestr do odczytu i zapisu, 32-bitowy. Zlicza zakończone polecenia z ustawioną flagą
FENCE
– licznik jest zwiększany o 1 (modulo2**32
), gdy dane polecenie (i wszystkie poprzednie polecenia) zostanie w pełni zakończone. (Jeśli licznik na początku wynosi 0 i zaczniemy wysyłać polecenia, po czym odczytamy wartośćx
, oznacza to, że polecenia0..x-1
zostały w pełni zakońćzone.)BAR0 + 0x0014: FENCE_WAIT
Rejestr do odczytu i zapisu, 32-bitowy (tak jak
FENCE_COUNTER
). GdyFENCE_COUNTER
zostanie zwiększony przez urządzenie i osiągnie przez to wartość równą wartości tego rejestru, zostanie wyzwolone przerwanieFENCE
.
FENCE_WAIT
pozwala na zaawansowaną implementację oczekiwania na wysłane
wcześniej polecenia. Przykładowy mechanizm użycia wygląda następująco:
przed włączeniem urządzenia, inicjujemy
FENCE_COUNTER
na 0.na końcu każdej paczki poleceń, na zakończenie której chcemy czekać, wysyłamy polecenie z ustawioną flagą
FENCE
.dla każdego wysłanego polecenia z flagą
FENCE
pamiętamy jego odpowiadającą wartośćFENCE_COUNTER
(dla kolejnych poleceń, kolejno1, 2, 3, ...
, zawijając się modulo2**32
).nie dopuszczamy, by kiedykolwiek było więcej niż 2**32 poleceń z flagą
FENCE
“w locie” (w razie potrzeby czekając na zakończenie poprzednich poleceń przed wysłaniem kolejnego).jeśli w pewnym momencie uznamy, że chcemy oczekiwać na wykonanie wysłanego wcześniej polecenia:
czyścimy przerwanie
FENCE
.ustawiamy
FENCE_WAIT
na numer polecenia, na które chcemy oczekiwać.czytamy
FENCE_COUNTER
i sprawdzamy, czy polecenie już się wykonało.jeśli się nie wykonało, czekamy na wyzwolenie przerwania
FENCE
.
Przed rozpoczęciem pracy, sterownik może zainicjować FENCE_COUNTER
na
pożądaną wartość początkową (prawdopodobnie 0). Pisanie do tego rejestru,
gdy urządzenie jest już aktywne, jest prawdopodobnie złym pomysłem.
Rejestry sterujące¶
Blok sterujący zajmuje się nadzorowaniem pracy całego urządzenia. Jego rejestry to:
BAR0 + 0x0000: ENABLE
Rejestr kontrolujący pracę pozostałych bloków, dostępny do odczytu i zapisu. Ma wiele bitów, z których każdy kontroluje pracę jednego bloku urządzenia (1 – blok jest aktywny i może wykonywać pracę, 0 – blok jest nieaktywny). Wyłączenie bloku w tym rejestrze nie spowoduje jego resetu – po ponownym włączeniu, blok kontynuuje pracę od momentu, w którym skończył. Bity:
bit 0:
CMD_FETCH
– blok wczytywania poleceń.bit 1:
CMD_SEND
– dostęp do kolejki poleceń przezCMD_SEND
.bit 2:
FE
– blok rysujący, przetwarzanie poleceń.bit 3:
XY
– blok rysujący, przeliczanie współrzędnych na adresy.bit 4:
TEX
– blok rysujący, obsługa tekstur kolumnowych.bit 5:
FLAT
– blok rysujący, obsługa tekstur płaskich.bit 6:
FUZZ
– blok rysujący, efektFUZZ
.bit 7:
SR
– blok rysujący, wczytywanie pikseli z bufora ramki.bit 8:
OG
– blok rysujący, zbieranie danych i mapy kolorówbit 9:
SW
– blok rysujący, mapy przezroczystości i zapis do bufora ramki.
Rejestr jest ustawiany na 0 przez reset maszyny, blokując urządzenie do momentu załadowania sterownika. W przypadku zgłoszenia błędu przez blok rysujący, urządzenie wyzeruje odpowiedni bit w tym rejestrze, zatrzymując blok do momentu naprawienia problemu przez sterownik.
Warning
Przed włączeniem urządzenia, należy pamiętać o:
załadowaniu mikrokodu przez
FE_CODE_ADDR
iFE_CODE_WINDOW
zresetowaniu wszystkich bloków w
RESET
,zainicjowaniu rejestrów
CMD_*_IDX
(jeśli używamy bloku wczytywania poleceń)wyzerowaniu przerwań (w
INTR
)
BAR0 + 0x0004: RESET
Rejestr resetowania stanu urządzenia, dostępny tylko do zapisu. Ma wiele bitów, odpowiadających blokom urządzenia. Przy zapisie, wszystkie bloki, których bity są równe 1 w zapisanej wartości, są resetowane: wszystkie polecenia w trakcie wykonywania są przerywane i kasowane, kolejki poleceń i pamięci podręczne są czyszczone. Bity:
bit 2:
FE
– blok rysujący, przetwarzanie poleceń.bit 3:
XY
– blok rysujący, przeliczanie współrzędnych na adresy.bit 4:
TEX
– blok rysujący, obsługa tekstur kolumnowych.bit 5:
FLAT
– blok rysujący, obsługa tekstur płaskich.bit 6:
FUZZ
– blok rysujący, efektFUZZ
.bit 7:
SR
– blok rysujący, wczytywanie pikseli z bufora ramki.bit 8:
OG
– blok rysujący, zbieranie danych i mapy kolorówbit 9:
SW
– blok rysujący, mapy przezroczystości i zapis do bufora ramki.bit 10:
STATS
– blok statystyk. Wszystkie liczniki są ustawiane na 0.bit 11:
TLB
– bufory TLB. Wszystkie wpisy tabeli stron zapisane w TLB są kasowane i, w razie potrzeby, zostaną wczytane na nowo.bit 12:
TEX_CACHE
– pamięć podręczna tekstury kolumnowej.bit 13:
FLAT_CACHE
– pamięć podręczna tekstury płaskiej.bit 14:
SW_CACHE
– pamięć podręczna mapy przezroczystości.bit 16:
FIFO_FECMD
– główna kolejka poleceń bloku rysującego.bit 17:
FIFO_XYCMD
– wewnętrzna kolejka urządzenia.bit 18:
FIFO_TEXCMD
– wewnętrzna kolejka urządzenia.bit 19:
FIFO_FLATCMD
– wewnętrzna kolejka urządzenia.bit 20:
FIFO_FUZZCMD
– wewnętrzna kolejka urządzenia.bit 21:
FIFO_OGCMD
– wewnętrzna kolejka urządzenia.bit 22:
FIFO_SWCMD
– wewnętrzna kolejka urządzenia.bit 24:
FIFO_XYOUTR
– wewnętrzna kolejka urządzenia.bit 25:
FIFO_XYOUTW
– wewnętrzna kolejka urządzenia.bit 26:
FIFO_SROUT
– wewnętrzna kolejka urządzenia.bit 27:
FIFO_TEXOUT
– wewnętrzna kolejka urządzenia.bit 28:
FIFO_FLATOUT
– wewnętrzna kolejka urządzenia.bit 29:
FIFO_FUZZOUT
– wewnętrzna kolejka urządzenia.bit 30:
FIFO_OGOUT
– wewnętrzna kolejka urządzenia.bit 31:
FIFO_XYSYNC
– wewnętrzna kolejka urządzenia.
Użycie bitów
TLB
,STATS
i*_CACHE
w dowolnym momencie nie wpłynie negatywnie na pracę urządzenia. Wszystkie pozostałe bity powinny być używane w zasadzie tylko wtedy, gdy resetujemy całe urządzenie (gdyż w przeciwnym przypadku stan poszczególnych bloków się rozsynchronizuje).Warning
Przed użyciem urządzenia (włączeniem bloku rysującego w
ENABLE
) należy zresetować cały blok rysujący (zapisując0xff7f7ffc
do tego rejestru) – w przeciwnym wypadku, wewnętrzne rejestry stanu urządzenia mogą zawierać śmieci, powodując wykonanie nieokreślonych poleceń przez urządzenie (w tym zapisu do dowolnej pamięci) bądź zawieszenie urządzenia.Blok wczytywania poleceń nie ma swojego bitu resetującego – jeśli sterownik chce go użyć, powinien zamiast tego zainicjować rejestry
CMD_*_IDX
.
Przerwania¶
Urządzenie wewnętrznie używa 10 przerwań (które są agregowane w jedno przerwanie PCI):
FENCE
– przerwanie używane do powiadomienia sterownika o wykonaniu polecenia. Wyzwalane, gdy licznik poleceń osiągnie wartośćFENCE_WAIT
.PONG_SYNC
– wyzwalane przez polecenie z flagąPING_SYNC
.PONG_ASYNC
– wyzwalane przez polecenie z flagąPING_ASYNC
.FE_ERROR
– wyzwalane, gdy blok rysujący zauważy błędne polecenie.CMD_OVERFLOW
– wyzwalane, gdy sterownik spróbuje pisać doCMD_SEND
, gdy nie ma już wolnego miejsca w kolejce, lub blokCMD_SEND
jest wyłączony.SURF_DST_OVERFLOW
– wyzwalane, gdy blok rysujący spróbuje pisać lub czytać piksel o współrzędnych poza szerokością docelowego bufora ramki (ustaloną przezSURF_DST_WIDTH
).SURF_SRC_OVERFLOW
– wyzwalane, gdy blok rysujący spróbuje lub czytać piksel o współrzędnych poza szerokością źródłowego bufora ramki (ustaloną przezSURF_SRC_WIDTH
).PAGE_FAULT_CMD
– wyzwalane, gdy blok wczytywania poleceń użyć strony oznaczonej w tabeli stron jako nieobecna.PAGE_FAULT_SURF_DST
– wyzwalane, gdy blok rysujący spróbuje użyć strony oznaczonej w tabeli stron jako nieobecna bądź tylko do odczytu przy pisaniu lub czytaniu docelowego bufora ramki.PAGE_FAULT_SURF_SRC
– jak wyżej, ale do źródłowego bufora ramki.PAGE_FAULT_TEXTURE
– jak wyżej, ale do czytania tekstury kolumnowej.PAGE_FAULT_FLAT
– jak wyżej, ale do czytania tekstury płaskiej.PAGE_FAULT_TRANSLATION
– jak wyżej, ale do czytania map kolorów do zmiany palety.PAGE_FAULT_COLORMAP
– jak wyżej, ale do czytania map kolorów do efektów i oświetlenia.PAGE_FAULT_TRANMAP
– jak wyżej, ale do czytania mapy przezroczystości.
Warning
Wyzwolenie przerwania SURF_*_OVERFLOW
jest zasadniczo
błędem krytycznym – nie ma sensownej możliwości obsługi tego błędu innej
niż pełny reset urządzenia. To przerwanie (tak jak i FE_ERROR
czy
CMD_OVERFLOW
) nie powinno się nigdy zdarzyć z poprawnym sterownikiem.
Przerwania PAGE_FAULT_*
teoretycznie mogą zostać użyte do ładowania
stron na żądanie, ale w praktyce nie jest to zbyt przydatne i w zasadzie
służą również do wykrywania błędów sterownika.
Każde z powyższych przerwań może być w danej chwili aktywne bądź nie.
Przerwanie staje się aktywne, gdy zajdzie odpowiednie zdarzenie. Przerwanie
staje się nieaktywne, gdy sterownik zapisze 1 do odpowiedniego bitu
w rejestrze INTR
. Aby sprawdzić, które przerwania są aktywne, należy
przeczytać rejestr INTR
.
Niezależnie, każde z powyższych przerwań może być w danej chwili włączone
bądź nie. Sterownik może ustawić włączony podzbiór przerwań przez zapis
odpowiedniej maski do rejestru INTR_ENABLE
. Urządzenie zgłasza przerwanie
na swojej linii przerwań PCI wtedy i tylko wtedy, gdy istnieje włączone
i aktywne przerwanie.
BAR0 + 0x0008: INTR
Rejestr statusu przerwań. Ma 15 bitów, każdy odpowiadający jednemu rodzajowi przerwań:
bit 0:
FENCE
,bit 1:
PONG_SYNC
,bit 2:
PONG_ASYNC
,bit 4:
FE_ERROR
,bit 5:
CMD_OVERFLOW
bit 6:
SURF_DST_OVERFLOW
bit 7:
SURF_SRC_OVERFLOW
bit 8:
PAGE_FAULT_CMD
bit 9:
PAGE_FAULT_SURF_DST
bit 10:
PAGE_FAULT_SURF_SRC
bit 11:
PAGE_FAULT_TEXTURE
bit 12:
PAGE_FAULT_FLAT
bit 13:
PAGE_FAULT_TRANSLATION
bit 14:
PAGE_FAULT_COLORMAP
bit 15:
PAGE_FAULT_TRANMAP
Odczyt tego rejestru zwróci 1 dla aktywnych przerwań, 0 dla nieaktywnych. Zapis spowoduje wyzerowanie (ustawienie na nieaktywne) wszystkich przerwań, dla których został zapisany bit 1. Przykładowo, zapisanie 0x12 spowoduje wyzerowanie przerwań
FE_ERROR
orazPONG_SYNC
.BAR0 + 0x000c: INTR_ENABLE
Rejestr włączania przerwań, dostępny do odczytu i zapisu. Ma takie same bity jak
INTR
. 1 oznacza przerwanie włączone, a 0 – przerwanie wyłączone. Przy resecie maszyny, rejestr zostaje ustawiony na 0, blokując możliwość zgłaszania przerwania PCI przez urządzenie do momentu załadowania sterownika.
Mikrokod¶
Blok rysujący opiera się na zaawansowanym procesorze odpowiadającym za
przetwarzanie poleceń. Przed włączeniem bloku rysującego w ENABLE
,
sterownik musi załadować odpowiedni mikrokod na urządzenie – w przeciwnym
wypadku, zachowanie urządzenia jest kompletnie niezdefiniowane. Mikrokod jest
tablicą 32-bitowych słów, maksymalnie 4096-elementową. Jest dostarczany
w pliku https://github.com/koriakin/harddoom2/blob/master/doomcode2.bin w formacie little-endian, a jego format
i działanie jest tajemnicą handlową firmy DoomDevices® (i nie należy zadawać
niewygodnych pytań na jego temat). Można go również pobrać jako plik nagłówkowy
gotowy do załączenia do kodu w C: https://github.com/koriakin/harddoom2/blob/master/doomcode2.h .
Do ładowania mikrokodu służą następujące rejestry:
BAR0 + 0x0100: FE_CODE_ADDR
Indeks w tablicy, który będziemy widoczny przez
FE_CODE_WINDOW
(dostępny do odczytu i zapisu).BAR0 + 0x0104: FE_CODE_WINDOW
Okno do tablicy mikrokodu – odczytuje bądź zapisuje komórkę wybrana przez
FE_CODE_ADDR
, po czym zwiększaFE_CODE_ADDR
o 1 (pozwalając na szybki sekwencyjny odczyt bądź zapis wielu komórek tablicy).
Uruchomienie urządzenia¶
Poprawna procedura uruchamiania urządzenia jest następująca (użycie dowolnej innej procedury spowoduje utratę gwarancji i brak możliwości zwrotu urządzenia):
zapisać 0 do
FE_CODE_ADDR
,wczytać zawartość pliku
doomcode2.bin
jako tablicę 32-bitowych słów little-endian,kolejno zapisać wszystkie wczytane słowa do
FE_CODE_WINDOW
,zresetować wszystkie bloki urządzenia przez zapis
0xff7f7ffc
doRESET
,zainicjować
CMD_PT
,CMD_SIZE
iCMD_*_IDX
, jeśli chcemy użyć bloku wczytywania pleceń,wyzerować
INTR
przez zapis0xfff7
,włączyć używane przez nas przerwania w
INTR_ENABLE
,zainicjować
FENCE_COUNTER
, jeśli czujemy taką potrzebę,włączyć wszystkie bloki urządzenia w
ENABLE
(być może z wyjątkiemCMD_FETCH
).
Po wykonaniu tej procedury można rozpocząć wysyłanie poleceń do urządzenia
(przez CMD_SEND
lub CMD_WRITE_IDX
).
Żeby wyłączyć urządzenie, wystarczy zapisać 0 do ENABLE
oraz
INTR_ENABLE
, po czym przeczytać dowolny rejestr urządzenia.
Inne rejestry¶
Dokumentacja sprzętowa nigdy nie mówi całej prawdy (i rzadko mówi tylko prawdę). Urządzenie może mieć inne rejestry i polecenia ponad wyżej wymienione, lecz używanie ich w ostatecznym sterowniku jest złym pomysłem – są to po prostu szczegóły implementacyjne. Mogą jednak być przydatne przy debugowaniu…
Poniższe rejestry nie są potrzebne do napisania sterownika, ale mają sporą szansę się przydać (oprócz nich, urządzenie zawiera wiele nieudokumentowanych rejestrów).
Rejestry błędów¶
W przypadku popełnienia błędu przez sterownik, przydatne może być przeczytanie następujących rejestrów:
BAR0 + 0x004: STATUS
Rejestr statusu, tylko do odczytu. Ma wiele bitów, odpowiadających blokom urządzenia. Gdy bit jest równy 1, dany blok ma pracę do wykonania (i, jeśli odpowiedni bit w
ENABLE
jest równy 1, będzie próbował ją wykonać). Gdy bit jest równy 0, dany blok nie ma nic do zrobienia (ale może się to w każdej chwili zmienić, jeżeli inny blok zleci mu jakieś zadania). Bity:bit 0:
CMD_FETCH
– blok wczytywania poleceń (ten bit jest efektywnie równyCMD_READ_IDX != CMD_WRITE_IDX
).bit 2:
FE
– blok rysujący, przetwarzanie poleceń.bit 3:
XY
– blok rysujący, przeliczanie współrzędnych na adresy.bit 4:
TEX
– blok rysujący, obsługa tekstur kolumnowych.bit 5:
FLAT
– blok rysujący, obsługa tekstur płaskich.bit 6:
FUZZ
– blok rysujący, efektFUZZ
.bit 7:
SR
– blok rysujący, wczytywanie pikseli z bufora ramki.bit 8:
OG
– blok rysujący, zbieranie danych i mapy kolorówbit 9:
SW
– blok rysujący, mapy przezroczystości i zapis do bufora ramki.bit 16:
FIFO_FECMD
– główna kolejka poleceń bloku rysującego.bit 17:
FIFO_XYCMD
– wewnętrzna kolejka urządzenia.bit 18:
FIFO_TEXCMD
– wewnętrzna kolejka urządzenia.bit 19:
FIFO_FLATCMD
– wewnętrzna kolejka urządzenia.bit 20:
FIFO_FUZZCMD
– wewnętrzna kolejka urządzenia.bit 21:
FIFO_OGCMD
– wewnętrzna kolejka urządzenia.bit 22:
FIFO_SWCMD
– wewnętrzna kolejka urządzenia.bit 24:
FIFO_XYOUTR
– wewnętrzna kolejka urządzenia.bit 25:
FIFO_XYOUTW
– wewnętrzna kolejka urządzenia.bit 26:
FIFO_SROUT
– wewnętrzna kolejka urządzenia.bit 27:
FIFO_TEXOUT
– wewnętrzna kolejka urządzenia.bit 28:
FIFO_FLATOUT
– wewnętrzna kolejka urządzenia.bit 29:
FIFO_FUZZOUT
– wewnętrzna kolejka urządzenia.bit 30:
FIFO_OGOUT
– wewnętrzna kolejka urządzenia.bit 31:
FIFO_XYSYNC
– wewnętrzna kolejka urządzenia.
BAR0 + 0x0110: FE_ERROR_CODE
Kod ostatnio zgłoszonego błędu
FE_ERROR
. Zdefiniowane są następujące kody:0x00
:RESERVED_TYPE
– nieznany typ polecenia.0x01
:RESERVED_BIT
– nieużywany bit nie jest ustawiony na 0.0x02
:SURF_WIDTH_ZERO
– zerowa szerokość bufora ramki.0x03
:SURF_WIDTH_OVF
– bufor ramki szerszy niż 2048 pikseli.0x04
:DRAW_COLUMN_REV
– pierwszy piksel kolumny ma większą współrzędną Y niż drugi.0x05
:DRAW_FUZZ_REV
– pierwszy piksel kolumny ma większą współrzędną Y niż drugi.0x06
:DRAW_SPAN_REV
– pierwszy piksel paska ma większą współrzędną X niż drugi.
BAR0 + 0x0180 + i * 4, i < 8: FE_REG
Polecenie, którego dotyczy ostatnio zgłoszony błąd
FE_ERROR
.BAR0 + 0x0600: XY_STATE
Szerokości buforów ramki obowiązujące w momencie zgłoszenia błędu
SURF_OVERFLOW
. Bity:bity 0-5:
SURF_DST_WIDTH
.bity 8-13:
SURF_SRC_WIDTH
.
BAR0 + 0x0608: XY_DST_DATA
W przypadku błędów
PAGE_FAULT_SURF_DST
orazSURF_DST_OVERFLOW
można tu przeczytać współrzędne, które wywołały błąd:bity 0-4: bity 6-10 współrzędnej x (bity 0-5 nie są zapisywane)
bity 5-15: współrzędna y
BAR0 + 0x060c: XY_SRC_DATA
Jak wyżej, ale do
PAGE_FAULT_SURF_SRC
iSURF_SRC_OVERFLOW
.
BAR0 + 0x0080: TLB_PT_CMD
BAR0 + 0x0084: TLB_PT_SURF_DST
BAR0 + 0x0088: TLB_PT_SURF_SRC
BAR0 + 0x008c: TLB_PT_TEXTURE
BAR0 + 0x0090: TLB_PT_FLAT
BAR0 + 0x0094: TLB_PT_TRANSLATION
BAR0 + 0x0098: TLB_PT_COLORMAP
BAR0 + 0x009c: TLB_PT_TRANMAP
Adres początku tabeli stron używanej w momencie wyzwolenia błędu
PAGE_FAULT_*
(przesunięty w prawo o 8 bitów, jak w poleceniuSETUP
).
BAR0 + 0x00c0: TLB_VADDR_CMD
BAR0 + 0x00c4: TLB_VADDR_SURF_DST
BAR0 + 0x00c8: TLB_VADDR_SURF_SRC
BAR0 + 0x00cc: TLB_VADDR_TEXTURE
BAR0 + 0x00d0: TLB_VADDR_FLAT
BAR0 + 0x00d4: TLB_VADDR_TRANSLATION
BAR0 + 0x00d8: TLB_VADDR_COLORMAP
BAR0 + 0x00dc: TLB_VADDR_TRANMAP
Adres wirtualny, który spowodował błąd
PAGE_FAULT_*
. Niskie 6 bitów nie jest zapisywane (jest zawsze równe 0).
Blok statystyk¶
Blok rysujący zbiera różnorodne statystyki dotyczące pracy urządzenia. Są one bezpośrednio widoczne jako rejestry MMIO. Każdy taki rejestr jest 32-bitowym licznikiem (który może się przekręcić – urządzenie nie robi wtedy nic specjalnego). Te liczniki zliczają następujące zdarzenia:
BAR0 + 0x0400: STATS_FE_COPY_RECT_HORIZONTAL
– polecenieCOPY_RECT
realizowane poziomoBAR0 + 0x0404: STATS_FE_COPY_RECT_LINE
– jedna linia poziomego poleceniaCOPY_RECT
BAR0 + 0x0408: STATS_FE_COPY_RECT_VERTICAL
– polecenieCOPY_RECT
realizowane pionowoBAR0 + 0x040c: STATS_FE_FILL_RECT_HORIZONTAL
– polecenieFILL_RECT
realizowane poziomoBAR0 + 0x0410: STATS_FE_FILL_RECT_LINE
– jedna linia poziomego poleceniaFILL_RECT
BAR0 + 0x0414: STATS_FE_FILL_RECT_VERTICAL
– polecenieFILL_RECT
realizowane pionowoBAR0 + 0x0418: STATS_FE_DRAW_BACKGROUND
– polecenieDRAW_BACKGROUND
BAR0 + 0x041c: STATS_FE_DRAW_BACKGROUND_LINE
– jedna linia poleceniaDRAW_BACKGROUND
BAR0 + 0x0420: STATS_FE_DRAW_LINE_HORIZONTAL
– polecenieDRAW_LINE
realizowane poziomoBAR0 + 0x0424: STATS_FE_DRAW_LINE_VERTICAL
– polecenieDRAW_LINE
realizowane pionowoBAR0 + 0x0428: STATS_FE_DRAW_LINE_H_CHUNK
– rysowanie prostokąta N×1 linii poziomejBAR0 + 0x042c: STATS_FE_DRAW_LINE_V_CHUNK
– rysowanie prostokąta 1×N linii pionowejBAR0 + 0x0430: STATS_FE_DRAW_LINE_H_PIXEL
– rysowanie piksela linii poziomejBAR0 + 0x0434: STATS_FE_DRAW_LINE_V_PIXEL
– rysowanie piksela linii pionowejBAR0 + 0x0438: STATS_FE_DRAW_COLUMN_BATCH
– grupa poleceńDRAW_COLUMN
przetwarzana równolegleBAR0 + 0x043c: STATS_FE_DRAW_FUZZ_BATCH
– grupa poleceńDRAW_FUZZ
przetwarzana równolegleBAR0 + 0x0440: STATS_FE_DRAW_COLUMN
– polecenieDRAW_COLUMN
BAR0 + 0x0444: STATS_FE_DRAW_FUZZ
– polecenieDRAW_FUZZ
BAR0 + 0x0448: STATS_FE_DRAW_COLUMN_CHUNK
– jeden pionowy segment grupy poleceńDRAW_COLUMN
BAR0 + 0x044c: STATS_FE_DRAW_FUZZ_CHUNK
– jeden pionowy segment grupy poleceńDRAW_FUZZ
BAR0 + 0x0450: STATS_FE_PING_ASYNC
– polecenie z flagąPING_ASYNC
BAR0 + 0x0454: STATS_FE_LOAD_FLAT
– załadowanie nowej tekstury płaskiejBAR0 + 0x0458: STATS_FE_LOAD_TRANSLATION
– załadowanie nowej mapy kolorów do zmiany paletyBAR0 + 0x045c: STATS_FE_LOAD_COLORMAP
– załadowanie nowej mapy kolorów do efektówBAR0 + 0x0460: STATS_FE_BATCH_END_MISMATCH_COLORMAP
– przerwanie paczki poleceń przez zmianę aktywnej mapy kolorówBAR0 + 0x0464: STATS_FE_BATCH_END_MISMATCH_TEX_DIMS
– przerwanie paczki poleceń przez zmianę aktywnej wysokości bądź limitu teksturyBAR0 + 0x0468: STATS_FE_BATCH_END_MISMATCH_CMD
– przerwanie paczki poleceń przez wysłanie nowego typu poleceniaBAR0 + 0x046c: STATS_FE_BATCH_END_MISMATCH_FUZZ
– przerwanie paczki poleceń przez zmianę granic efektuDRAW_FUZZ
BAR0 + 0x0470: STATS_FE_BATCH_END_SIZE
– przerwanie paczki poleceń przez osiągnięcie maksymalnego rozmiaru paczkiBAR0 + 0x0474: STATS_FE_BATCH_END_XY
– przerwanie paczki poleceń przez niepasujące współrzędne kolejnej kolumnyBAR0 + 0x0478: STATS_FE_BATCH_END_SYNC
– przerwanie paczki poleceń przez wysłanie flagi synchronizacyjnej (FENCE
lubPING_SYNC
)BAR0 + 0x047c: STATS_FE_DRAW_SPAN
– polecenieDRAW_SPAN
BAR0 + 0x0480: STATS_TLB_CMD_HIT
– trafienie w buforze TLB dla bufora poleceń.BAR0 + 0x0484: STATS_TLB_SURF_DST_HIT
– j/w, docelowy bufor ramki.BAR0 + 0x0488: STATS_TLB_SURF_SRC_HIT
– j/w, źródłowy bufor ramki.BAR0 + 0x048c: STATS_TLB_TEXTURE_HIT
– j/w, tekstura kolumnowa.BAR0 + 0x0490: STATS_TLB_FLAT_HIT
– j/w, tekstura płaska.BAR0 + 0x0494: STATS_TLB_TRANSLATION_HIT
– j/w, mapa kolorów do zmiany palety.BAR0 + 0x0498: STATS_TLB_COLORMAP_HIT
– j/w, mapa kolorów do efektów.BAR0 + 0x049c: STATS_TLB_TRANMAP_HIT
– j/w, mapa przezroczystości.BAR0 + 0x04a0: STATS_TLB_CMD_MISS
– chybienie w buforze TLB dla bufora poleceń.BAR0 + 0x04a4: STATS_TLB_SURF_DST_MISS
– j/w, docelowy bufor ramki.BAR0 + 0x04a8: STATS_TLB_SURF_SRC_MISS
– j/w, źródłowy bufor ramki.BAR0 + 0x04ac: STATS_TLB_TEXTURE_MISS
– j/w, tekstura kolumnowa.BAR0 + 0x04b0: STATS_TLB_FLAT_MISS
– j/w, tekstura płaska.BAR0 + 0x04b4: STATS_TLB_TRANSLATION_MISS
– j/w, mapa kolorów do zmiany palety.BAR0 + 0x04b8: STATS_TLB_COLORMAP_MISS
– j/w, mapa kolorów do efektów.BAR0 + 0x04bc: STATS_TLB_TRANMAP_MISS
– j/w, mapa przezroczystości.BAR0 + 0x04c0: STATS_TLB_CMD_CHANGE
– zmiana aktywnej tabeli stron dla bufora ramki.BAR0 + 0x04c4: STATS_TLB_SURF_DST_CHANGE
– j/w, docelowy bufor ramki.BAR0 + 0x04c8: STATS_TLB_SURF_SRC_CHANGE
– j/w, źródłowy bufor ramki.BAR0 + 0x04cc: STATS_TLB_TEXTURE_CHANGE
– j/w, tekstura kolumnowa.BAR0 + 0x04d0: STATS_TLB_FLAT_CHANGE
– j/w, tekstura płaska.BAR0 + 0x04d4: STATS_TLB_TRANSLATION_CHANGE
– j/w, mapa kolorów do zmiany palety.BAR0 + 0x04d8: STATS_TLB_COLORMAP_CHANGE
– j/w, mapa kolorów do efektów.BAR0 + 0x04dc: STATS_TLB_TRANMAP_CHANGE
– j/w, mapa przezroczystości.BAR0 + 0x04e0: STATS_TEX_CACHE_HIT
– trafienie teksela w pamięci podręcznej tekstury kolumnowejBAR0 + 0x04e4: STATS_TEX_CACHE_SPEC_HIT
– trafienie spekulatywnego teksela w pamięci podręcznej tekstury kolumnowejBAR0 + 0x04e8: STATS_TEX_CACHE_MISS
– chybienie teksela (czyli wczytanie 64 bajtów z tekstury)BAR0 + 0x04ec: STATS_TEX_CACHE_SPEC_MISS
– chybienie spekulatywnego teksela (czyli porzucenie spekulatywnego teksturowania danej kolumny)BAR0 + 0x04f0: STATS_FLAT_SPAN_BLOCK
– oteksturowanie bloku pikseli teksturą płaskąBAR0 + 0x04f4: STATS_FLAT_SPAN_PIXEL
– oteksturowanie piksela teksturą płaskąBAR0 + 0x04f8: STATS_FLAT_CACHE_HIT
– trafienie teksela w pamięci podręcznej tekstury płaskiejBAR0 + 0x04fc: STATS_FLAT_CACHE_MISS
– chybienie teksela (czyli wczytanie 64 bajtów z tekstury)BAR0 + 0x0500: STATS_OG_DRAW_BUF_BLOCK
– rysowanie bloku pikseli przezFILL_RECT
,DRAW_LINE
lubDRAW_BACKGROUND
BAR0 + 0x0504: STATS_OG_DRAW_BUF_PIXEL
– rysowanie piksela przezFILL_RECT
,DRAW_LINE
lubDRAW_BACKGROUND
BAR0 + 0x0508: STATS_OG_COPY_BLOCK
– rysowanie bloku pikseli przezCOPY_RECT
BAR0 + 0x050c: STATS_OG_COPY_PIXEL
– rysowanie piksela przezCOPY_RECT
BAR0 + 0x0510: STATS_OG_TRANSLATION_BLOCK
– przetwarzanie bloku pikseli przez flagęTRANSLATION
BAR0 + 0x0514: STATS_OG_COLORMAP_BLOCK
– przetwarzanie bloku pikseli przez flagęCOLORMAP
BAR0 + 0x0518: STATS_OG_TRANSLATION_PIXEL
– przetwarzanie piksela przez flagęTRANSLATION
BAR0 + 0x051c: STATS_OG_COLORMAP_PIXEL
– przetwarzanie piksela przez flagęCOLORMAP
BAR0 + 0x0520: STATS_OG_FUZZ_PIXEL
– rysowanie piksela przezDRAW_COLUMN
zFUZZ
BAR0 + 0x0524: STATS_SW_XFER
– rysowanie ciągłej grupy pikseliBAR0 + 0x0528: STATS_SW_FENCE
– przetworzenie polecenia z flagąFENCE
BAR0 + 0x052c: STATS_SW_PING_SYNC
– przetworzenie polecenia z flagąPING_SYNC
BAR0 + 0x0530: STATS_SW_TRANMAP_BLOCK
– przetwarzanie bloku pikseli przez flagęTRANMAP
BAR0 + 0x0534: STATS_SW_TRANMAP_PIXEL
– przetwarzanie piksela przez flagęTRANMAP
BAR0 + 0x0538: STATS_SW_TRANMAP_HIT
– trafienie piksela w pamięci podręcznej mapy przezroczystościjBAR0 + 0x053c: STATS_SW_TRANMAP_MISS
– chybienie piksela w tej mapie (czyli wczytanie 64 bajtów z mapy)BAR0 + 0x0540: STATS_FIFO_FECMD
– przetworzenie polecenia od użytkownika przez urządzenieBAR0 + 0x0544: STATS_FIFO_XYCMD
– przetworzenie polecenia wewnętrznego przez jednostkęXY
BAR0 + 0x0548: STATS_FIFO_TEXCMD
– przetworzenie polecenia wewnętrznego przez jednostkęTEX
BAR0 + 0x054c: STATS_FIFO_FLATCMD
– przetworzenie polecenia wewnętrznego przez jednostkęFLAT
BAR0 + 0x0550: STATS_FIFO_FUZZCMD
– przetworzenie polecenia wewnętrznego przez jednostkęFUZZ
BAR0 + 0x0554: STATS_FIFO_OGCMD
– przetworzenie polecenia wewnętrznego przez jednostkęOG
BAR0 + 0x0558: STATS_FIFO_SWCMD
– przetworzenie polecenia wewnętrznego przez jednostkęSW
BAR0 + 0x055c: STATS_FIFO_XYSYNC
– przetworzenie polecenia z flagąINTERLOCK
BAR0 + 0x0560: STATS_FIFO_SROUT
– wczytanie bloku pikseli z bufora ramkiBAR0 + 0x0564: STATS_FIFO_TEXOUT
– oteksturowanie bloku pikseli teksturą kolumnowąBAR0 + 0x0568: STATS_FIFO_FLATOUT
– oteksturowanie bloku pikseli teksturą płaską bądź wczytanie bloku pikseli przezDRAW_BACKGROUND
BAR0 + 0x056c: STATS_FIFO_FUZZOUT
– nałożenie efektuFUZZ
na blok pikseliBAR0 + 0x0570: STATS_FIFO_OGOUT
– zapisanie bloku pikseli do bufora ramkiBAR0 + 0x0574: STATS_FIFO_TEXOUT_PIXEL
– narysowanie piksela przezDRAW_COLUMN
BAR0 + 0x0578: STATS_FIFO_OGOUT_PIXEL
– rysowanie piksela jakiegokolwiek typuBAR0 + 0x057c: STATS_FENCE_INTR
– przetworzenie poleceniaFENCE
powodującego przerwanie
Blok pikseli to maksymalnie 64 piksele różniące się tylko niskimi 6 bitami
współrzędnej X (urządzenie grupuje wszystkie rysowane oraz wczytywane piksele
w takie bloki). Dzieląc statystyki *_PIXEL
przez *_BLOCK
można
zmierzyć efektywność grupowania pikseli przez urządzenie. Dzieląc
STAT_TEX_COLUMN
przez STAT_FE_DRAW_COLUMN_TEX_BATCH
można zmierzyć
efektywność grupowania kolumn. Dzieląc statystyki *_HIT
przez *_HIT + *_MISS
można zmierzyć efektywność działania pamięci podręcznych i buforów TLB.
Zresetowanie bloku statystyk (w rejestrze RESET
) jest równoznaczne
z zapisem 0 do każdego z wyżej wymienionych liczników.