Copy Link
Add to Bookmark
Report

Reference guide to the TA registers

Dreamcast's profile picture
Published in 
Dreamcast technical
 · 28 Nov 2018

 
Reference guide to the TA registers

This is a continuation of my previous text 'ta-into.txt' which described how
to construct TA lists. This document provides information about the
TA registers.

Thanks must go to Dan Potter and Sergio Moreira for very helpful contributions.


reach me at: jlo@ludd.luth.se



Introduction

The TA works by receiving lists containing vertex information. Unlike most
architectures, the PVR core uses a technique known as deferred rendering
whereby no polygons are rendered until the whole scene has been setup. The
advantage is that the PVR will only render those polygons that are actually
visible thus creating a very high fillrate. The downside is that this requires
more memory in form of buffers. Since the Dreamcast has 8 Mb of VRAM this is
not that big of a problem. Besides the framebuffer, there are three buffers of
interest;

* The Vertex Buffer contains the information sent to the TA through the lists.

* The Object Pointer Buffer contains pointers into the Vertex Buffer for
objects that may appear inside a tile.

* The Tile Buffer contains pointers to the Object Pointer Buffer for every
primitive type (opaque polygon, translucent modifier etc)



The PVR can work in two different modes; vertex registration mode and vertex
rendering mode. If double-buffering is employed, vertex registration can take
place while rendering is underway, creating an efficient implementation of the
deferred rendering paradigm.



Vertex Buffer

The Vertex Buffer is the most simple one. It grows upwards in memory as more
information is sent to the TA. After setting it up, the PVR handles the
management of this buffer by itself so there is little do for the user.



Object Pointer Buffer

This buffer possesses the most complex structure of the three. Fortunately most
of it is managed by the PVR so the user doesn't have to worry too much about
its internal structure.

There are two different parts to this buffer. The first part consists of 5
matrices of Object Pointer Segments, one for each primitive type, arranged
in a special order, to be referenced from the Tile Buffer (described later).
This part of the buffer is fixed at a known size. The other part is variable
in size as new segments are allocated and linked from the first part.

The Object Pointer Segments are separate linked lists with the following
appearance;

Segment 0 for Tile 0, 0;
Object Pointer 0
Object Pointer 1
...
Object Pointer n
Pointer to Segment 1 for Tile 0, 0


The arrangement of the segments in memory is;

Segment 0, Tile 0, 0, opaque polygon
Segment 0, Tile 1, 0, opaque polygon
Segment 0, Tile 2, 0, opaque polygon
...
Segment 0, Tile x, 0, opaque polygon
Segment 0, Tile 0, 1, opaque polygon
Segment 0, Tile 1, 1, opaque polygon
Segment 0, Tile 2, 1, opaque polygon
...
Segment 0, Tile x, y, opaque polygon


The above is the Opaque Polygon Object Pointer Buffer Matrix. It is followed by
matrices for the rest of the primitives. The order (important) should be:

* Opaque Polygon
* Opaque Modifier
* Translucent Polygons
* Translucent Modifiers
* Punch-through Polygons

The sizes of the segments are controlled by register a05f8140;

a05f8140: (object pointer buffer control)
+---------------------------------------------------------------------
| 31-21 | 20 | 19-18 | 17-16 | 15-14 | 13-12 | 11-10 |
| n/a | unknown | n/a | punch-through | n/a | transmod | n/a |
+---------------------------------------------------------------------
-------------------------------------------------+
| 9-8 | 7-6 | 5-4 | 3-2 | 1-0 |
| transpoly | n/a | opaquemod | n/a | opaquepoly |
-------------------------------------------------+

unknown:
like name indicates :(
seems to always be set though


punch-through:
0: size_0: Punch-through Polygons disabled
1: size_8: 7 Object Pointers + 1 Segment Pointer
2: size_16: 15 Object Pointers + 1 Segment Pointer
3: size_32: 31 Object Pointers + 1 Segment Pointer

transmod:
0: size_0: Translucent Modifiers disabled
1: size_8: 7 Object Pointers + 1 Segment Pointer
2: size_16: 15 Object Pointers + 1 Segment Pointer
3: size_32: 31 Object Pointers + 1 Segment Pointer

transpoly:
0: size_0: Translucent Polygons disabled
1: size_8: 7 Object Pointers + 1 Segment Pointer
2: size_16: 15 Object Pointers + 1 Segment Pointer
3: size_32: 31 Object Pointers + 1 Segment Pointer

opaquemod:
0: size_0: Opaque Modifiers disabled
1: size_16: 7 Object Pointers + 1 Segment Pointer
2: size_32: 15 Object Pointers + 1 Segment Pointer
3: size_64: 31 Object Pointers + 1 Segment Pointer

opaquepoly:
0: size_0: opaque polygons disabled
1: size_16: 7 Object Pointers + 1 Segment Pointer
2: size_32: 15 Object Pointers + 1 Segment Pointer
3: size_64: 31 Object Pointers + 1 Segment Pointer


The Object Pointers are references to objects that appear inside the tile
associated with the segment. If there are more objects in one tile than fits
into one segment, the last word in the segment points to a new segment.
Notable here is that these new segments are allocated BEFORE the first
Object Pointer Buffer Matrix, so the linked lists actually grow downwards in
memory.



Tile Buffer

The PVR does not render the entire framebuffer when it is performing a
rendering sequence. Instead the framebuffer is divided into 32x32-pixel tiles
which the PVR processes seperately, reducing overhead by a large amount.
The Tile Buffer is divided into segments corresponding to the tiles the
framebuffer is split into. The size of the Tile Buffer is dependant on the
resolution of the framebuffer, ie. a 640x480 screen will make the Tile Buffer
contain 20x15 segments. The aspect ratio of the Tile Buffer should be written
to register a05f813c according to:

a05f813c: (tile buffer control)
+----------------+
| 31-16 | 15-0 |
| height | width |
+----------------+

height:
height of tile buffer in segments - 1

width:
width of tile buffer in segments - 1



The segments contain a control word followed by 5 pointers (one for each
primitive type). The control word has the following appearance:

+----------------------------------------------------+
| 31 | 30 | 29 | 28 | 27-15 | 13-8 | 7-2 | 1-0 |
| eob | ??? | sort | init | ??? | y | x | n/a |
+----------------------------------------------------+

eob: (set on last segment in Tile Buffer)
0: normal
1: end of Tile Buffer

sort:
0: autosorting translucent polygons off (the must be submitted
in sorted order to the TA)
1: autosorting translucent polygons on

init: (set on first segment in Tile Buffer)
0: normal
1: initialize Tile Buffer

y:
y position of the tile corresponding to this segment

x:
x position of the tile corresponding to this segment




The five words following are pointers into the Object Pointer Buffer. Bit 31
of the pointers is set when there is no primitive of that type. The order of
the pointers is as follows;

* opaque polygon
* opaque modifier
* translucent polygon
* translucent modifier
* punch-through polygon

Unlike the Vertex Buffer, the Tile Buffer must be setup manually before using
the TA. This is done by allocating a chunk of memory in the VRAM and filling
out the required Tile Buffer structure. If primitives of a specific type are
to be used, the Tile Segment must contain a pointer to the corresponding Object
Pointer Buffer Segment. Since the sizes of the Object Pointer Buffer Matrices
are known it is possible to calculate the location of this according to:

pointer = start_of_matrix + (width_of_tile_buffer * size_N * tile_Y)
+ (size_N * tile_X) (1)

where start_of_matrix is the address of the primitive's matrix and
size_N is the size of the segments in bytes.


The creation of the Tile Buffer need normally only be done once, at the very
beginning before any vertex registration or rendering is begun.



Sending vertex data to the Tile Accelerator

To be able to receive vertex data, the TA must have a Vertex Buffer in which
to put the received data aswell as an Object Pointer Buffer.

The register a05f8140 should be written with the size information for all the
different primitive types.

The register a05f8124 should be written with the address of the first
Object Pointer Buffer Matrix. Since this buffer has the potential to grow
arbitrarily large as more vertex data are received, register a05f812c contains
the last address that can be safely written to. Important to remember that the
Object Pointer Buffer actually grows downwards in memory so a05f812c should be
set to:

a05f812c = address_of_first_OPB_matrix - OPB_size (2)

To set up the Object Pointer Buffer, the start address should also be written
to register a05f8164 to initialize it. The current position in the
Object Pointer Buffer can be read from register a05f8134.

The Vertex Buffer start address should be written to register a05f8128 and the
end address to register a05f8130, because otherwise it could grow too large
and overwrite other data. a05f8138 contains the current position in
the vertex buffer.

To actually perform the initialization, 0x80000000 should be written to
register a05f8144 and then read (to clear the bit).

After this procedure has been performed vertex registration is possible.



Rendering vertex data to the framebuffer

To render data, vertex registration must have been initiated and finished. It
is then a simple matter of instructing the PVR where to get the data and kick
it off. Register a05f8020 should be written with the Vertex Buffer address and
register a05f802c with the address of the Tile Buffer. Register a05f8014 is
then written with all bits set to start the rendering procedure.



Summary of registers:

a05f8014: (start render)
+--------+
| 31-0 |
| render |
+--------+

render:
write 1 to all bits to start rendering procedure


a05f8020: (vertex buffer start, rendering mode)
+--------------+
| 31-24 | 23-0 |
| n/a | addr |
+--------------+

addr:
location of vertex buffer in VRAM (32-byte aligned)

a05f802c: (tile buffer start, rendering mode)
+--------------+
| 31-24 | 23-0 |
| n/a | addr |
+--------------+

addr:
location of tile buffer in VRAM (32-byte aligned)


a05f8124: (object pointer buffer start, registration mode)
+--------------+
| 31-24 | 23-0 |
| ??? | addr |
+--------------+

addr:
start of object pointer buffer in VRAM (32-byte aligned)

a05f8128: (vertex buffer start, registration mode)
+--------------+
| 31-24 | 23-0 |
| n/a | addr |
+--------------+

addr:
start of vertex buffer in VRAM (32-byte aligned)

a05f812c: (object pointer buffer end, registration mode)
+--------------+
| 31-24 | 23-0 |
| n/a | addr |
+--------------+

addr:
end of object pointer buffer in VRAM (128-byte aligned)

a05f8130: (vertex buffer end, registration mode)
+--------------+
| 31-24 | 23-0 |
| n/a | addr |
+--------------+

addr:
end of vertex buffer in VRAM (32-byte aligned)

a05f8134: (object pointer buffer position, registration mode)
+--------------+
| 31-23 | 22-0 |
| n/a | addr |
+--------------+

addr:
current object pointer buffer position according to;
(POSITION / 4) - size_N
where size_N is determined through register a05f8140

a05f8138: (vertex buffer position, registration mode)
+--------------+
| 31-23 | 23-0 |
| n/a | addr |
+--------------+

addr:
current vertex buffer position

a05f813c: (tile buffer control)
+----------------+
| 31-16 | 15-0 |
| height | width |
+----------------+

height:
height of tile buffer in segments - 1

width:
width of tile buffer in segments - 1


a05f8140: (object pointer buffer control)
+---------------------------------------------------------------------
| 31-21 | 20 | 19-18 | 17-16 | 15-14 | 13-12 | 11-10 |
| n/a | unknown | n/a | punch-through | n/a | transmod | n/a |
+---------------------------------------------------------------------
-------------------------------------------------+
| 9-8 | 7-6 | 5-4 | 3-2 | 1-0 |
| transpoly | n/a | opaquemod | n/a | opaquepoly |
-------------------------------------------------+

unknown:
like name indicates :(
seems to always be set though


punch-through:
0: size_0 - Punch-through Polygons disabled
1: size_8 - 7 Object Pointers + 1 Segment Pointer
2: size_16 - 15 Object Pointers + 1 Segment Pointer
3: size_32 - 31 Object Pointers + 1 Segment Pointer

transmod:
0: size_0 - Translucent Modifiers disabled
1: size_8 - 7 Object Pointers + 1 Segment Pointer
2: size_16 - 15 Object Pointers + 1 Segment Pointer
3: size_32 - 31 Object Pointers + 1 Segment Pointer

transpoly:
0: size_0 - Translucent Polygons disabled
1: size_8 - 7 Object Pointers + 1 Segment Pointer
2: size_16 - 15 Object Pointers + 1 Segment Pointer
3: size_32 - 31 Object Pointers + 1 Segment Pointer

opaquemod:
0: size_0 - Opaque Modifiers disabled
1: size_8 - 7 Object Pointers + 1 Segment Pointer
2: size_16 - 15 Object Pointers + 1 Segment Pointer
3: size_32 - 31 Object Pointers + 1 Segment Pointer

opaquepoly:
0: size_0 - Opaque Polygons disabled
1: size_8 - 7 Object Pointers + 1 Segment Pointer
2: size_16 - 15 Object Pointers + 1 Segment Pointer
3: size_32 - 31 Object Pointers + 1 Segment Pointer

a05f8144: (vertex registration init)
+-------------+
| 31 | 30-0 |
| init | n/a |
+-------------+

init:
0: normal
1: initialize vertex registration

a05f8164: (object pointer buffer init)
+--------------+
| 31-24 | 23-0 |
| n/a | addr |
+--------------+

addr:
address of object pointer buffer in VRAM (32-byte aligned)



Some Caveats

Nothing in this document is official; nothing should be expected to be correct.
I have tried hard to ensure that everything accurately reflects the reality
of the PVR, but there are no guarantees that this is the case.

If you find any inaccuracies, please contact me at: jlo@ludd.luth.se

← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT