Texture Cache and Drawing Speed
Texture cache structure, frame buffer access cycles and command FIFO of the GPU.
Overview
The drawing speed of the GPU is set by the number of read and write accesses to the frame buffer. Frames are first drawn into the frame buffer and then output to the display, so the time a primitive takes depends on its area and its type: a larger primitive writes more of the frame buffer, and a semi-transparent primitive must also read it.1 The texture cache (T-cache) reduces the reads that texture mapping needs.2
Whether the GPU or the CPU is the bottleneck can be found with DrawSync(). If the CPU is the bottleneck, DrawSync() returns at once; if the GPU is, DrawSync() blocks, and the time it waits measures the latency through the GPU. When the GPU is the bottleneck, optimizing the program code does not improve performance.1
Texture Cache
The texture cache is a high-speed buffer memory located between the GPU and the frame buffer, and its primary function is to improve drawing speed. The GPU scans a polygon horizontally to find the texel for each pixel. Although each pixel of a polygon is drawn only once, each texel is likely to be read more than once. Consequently, reading the texture pattern into the T-cache speeds up texture mapping compared with reading it directly from the frame buffer.2
When a texel is already in the T-cache, the frame buffer is not accessed and the texel is read from the cache. The T-cache holds its data from one polygon to the next. When polygons are drawn one after another, drawing is therefore faster if their textures fit in the T-cache.2
The T-cache is 2K bytes. Like the frame buffer it has a 2-dimensional address, which changes with the pixel mode of the polygon being drawn. The size of the T-cache for each pixel mode is as follows:3
| Pixel Mode | Size (width x length) |
|---|---|
| 4 bits/pixel | 64 x 64 pixels |
| 8 | 64 x 32 |
| 16 | 32 x 32 |
The Run-Time Library Overview gives the same sizes.1 However, Sony's developer FAQ and psx-spx both give the 8-bit size as 32 x 64.45
Cache Blocks
A texture page is divided into rectangular regions of the cache size, called cache blocks, which are numbered in sequence. In 4-bit mode the cache is 64 x 64, so a 256 x 256 texture page divides into 16 cache blocks, numbered 0 to 3 in the first row of blocks and 12 to 15 in the last.6
Cache Entries
Each cache block is divided further into regions of 16 x 1 texels called cache entries. In 4-bit mode there are 256 cache entries, and each line of the 64 x 64 block holds 4 of them. An entry holds a block number tag and 4 short words of texture data, so in 4-bit mode one entry holds 16 texels.67 The sizes depend on the mode, but there are always 256 entries:8
| Mode | Block | Number of blocks | Entry | Number of entries |
|---|---|---|---|---|
| 4 | 64 x 64 | 16 | 16 x 1 | 256 |
| 8 | 64 x 32 | 32 | 8 x 1 | 256 |
| 16 | 32 x 32 | 64 | 4 x 1 | 256 |
Hit and Miss
The block number saved in each entry decides whether a texel is in the cache. In 4-bit mode the block of texel (u, v) is block_id = (v >> 6) << 2 + (u >> 6), and its entry is entry_id = (v AND 3Fh) << 2 + (u AND 3Fh) >> 4. A texel is a hit when the block number stored in that entry equals block_id.7
Since each entry stores its own block number, texels from different blocks can be in the cache together as long as their entry numbers differ. The texels in (u, v) = (16, 16) to (79, 79) span several blocks but share no entry, so they are cached together. The texels in (8, 8) to (71, 71) fit in a 64 x 64 area, yet (8, 8) to (15, 8) and (64, 8) to (71, 8) use the same entries, so they cannot all be cached at once.7 Areas that are not contiguous, such as (0, 0) to (15, 15) and (80, 64) to (95, 79), can also be cached together when their entries do not overlap.8
When a texel is missing, the GPU reads the whole entry that contains it. In 4-bit mode this reads 15 extra texels, which help only if they are used before the entry is replaced. Because the 4-bit cache covers 64 x 64 texels, texels 64 apart share an entry. A primitive whose (u, v) range exceeds 64 therefore always misses. In the worst case the texture is turned 90 degrees to the screen and drawing speed drops by half. Since the drawing direction changes with the screen matrix and so with controller input, this can make drawing speed vary widely.89
CLUT Cache
The GPU also caches one CLUT. As long as the CLUT used by the primitives does not change, it stays cached and drawing remains fast. The texture cache and the CLUT cache are flushed automatically after an access to the frame buffer.4 psx-spx adds that the CLUT cache survives from one drawing command to the next and is invalidated when a different CLUT is used or GP0(01h) is sent.5
Access Cycles
A write access to the frame buffer corresponds directly to drawing. A read access takes place when a texture pattern is read and when drawing in semi-transparent mode. The access cycles are as follows:10
| Access direction | pixels/cycle | Notes |
|---|---|---|
| Write | 2 | SPRT, TILE, POLY_F3, POLY_F4 |
| Write | 1 | Other |
| Read | 1 | Texture mapping, semi-transparent rendering |
A 100 x 100 POLY_G4 therefore takes 10,000 cycles, while a 100 x 100 POLY_F4 of the same area takes 5,000, because a flat polygon writes 2 pixels per cycle.10 A texture adds read cycles. A 4-bit texture packs four texels into one 16-bit word, so four texels are read with one access, and an 8-bit texture two:1011
| Primitive | Mode | Reads | Writes | Total |
|---|---|---|---|---|
| POLY_FT4 | 4-bit | 10000/4 = 2500 | 10000 | 12500 |
| POLY_FT4 | 8-bit | 10000/2 = 5000 | 10000 | 15000 |
| POLY_FT4 | 16-bit | 10000 | 10000 | 20000 |
| SPRT | 4-bit | 10000/4 = 2500 | 5000 | 7500 |
| SPRT | 8-bit | 10000/2 = 5000 | 5000 | 10000 |
| SPRT | 16-bit | 10000 | 5000 | 15000 |
These figures assume that every texel misses the cache and that texels map 1 to 1. A 4-bit texture is the fastest.1011
When the texture is reduced the reads stay the same. A 4-bit primitive reduced by 2 horizontally still reads 100 x 100/4 = 2500 times, while it writes 50 x 100 = 5000 times, for 7500 cycles; halving the area does not halve the time. When a texture is enlarged, the same texels are used more than once and fewer reads are needed.11
With a cache hit a texel is used without a read. A 100 x 100 SPRT then takes 5000 cycles in every mode, against 7500, 10000 and 15000 cycles on a miss.11 For primitives of the same area, rendering speed is always faster with a cache hit. With a cache miss, a 4-bit texture is faster than an 8-bit one, which is faster than a 16-bit one.10
Clipping
Clipping also costs cycles. A polygon is clipped to the drawing area, and the parts of a polygon to the left of and above the drawing area generate empty cycles, including empty texture reads. The parts to the right of and below the drawing area do not.116
Command FIFO
GP0 has a command FIFO of 64 bytes (16 words). The drawing area and offset commands GP0(E3h) to GP0(E5h) and the NOP commands do not take FIFO space.1213 A combined libgpu primitive may not exceed 16 long words in total size.14
psx-spx states that the v0 GPU loses data when a DMA transfer to VRAM uses a block size above 10h words, which exceeds the FIFO. The v2 GPU with DRAM is fast enough during vertical blanking to accept blocks of 8C0h words.1516
References
-
^ a b c Sony Computer Entertainment Inc. Run-Time Library Overview. January 1999. Page 8-26, Table 8-13, Figure 8-11.
-
^ a b c Sony Computer Entertainment Inc. PlayStation Hardware. August 1998. Page 3-7.
-
^ Sony Computer Entertainment Inc. PlayStation Hardware. August 1998. Page 3-8, Table 3-2.
-
^ a b Sony Computer Entertainment. The Un-official PlayStation Development FAQ, LIBGPU Conference. Release v1.1. August 31, 1995. Item 1.2.
-
^ a b psx-spx. Graphics Processing Unit (GPU), GPU Texture Caching. https://psx-spx.consoledev.net/graphicsprocessingunitgpu/#gpu-texture-caching
-
^ a b c Sony Computer Entertainment Inc. Run-Time Library Overview. January 1999. Page 8-29, Figure 8-12, Figure 8-13.
-
^ a b c Sony Computer Entertainment Inc. Run-Time Library Overview. January 1999. Page 8-30, Figure 8-14.
-
^ a b c Sony Computer Entertainment Inc. Run-Time Library Overview. January 1999. Page 8-31, Table 8-20.
-
^ Sony Computer Entertainment Inc. Run-Time Library Overview. January 1999. Page 8-32.
-
^ a b c d e Sony Computer Entertainment Inc. Run-Time Library Overview. January 1999. Page 8-27, Tables 8-14 to 8-16.
-
^ a b c d e Sony Computer Entertainment Inc. Run-Time Library Overview. January 1999. Page 8-28, Tables 8-17 to 8-19.
-
^ psx-spx. Graphics Processing Unit (GPU), GPU I/O Ports (0x1f801810, 0x1f801814). https://psx-spx.consoledev.net/graphicsprocessingunitgpu/#gpu-io-ports-dma-channels-commands-vram
-
^ psx-spx. Graphics Processing Unit (GPU), GPU Rendering Attributes, Note, and GP0(00h) - NOP (?). https://psx-spx.consoledev.net/graphicsprocessingunitgpu/#gpu-other-commands
-
^ Sony Computer Entertainment Inc. Run-Time Library Overview. January 1999. Page 8-12.
-
^ psx-spx. Graphics Processing Unit (GPU), Summary of GPU Differences. https://psx-spx.consoledev.net/graphicsprocessingunitgpu/#gpu-versions
-
^ psx-spx. Graphics Processing Unit (GPU), Memory/Rendering Timings. https://psx-spx.consoledev.net/graphicsprocessingunitgpu/#gpu-versions