GPU/External Registers: Difference between revisions
m Fix a missing brace in calculation and make register more clear |
mNo edit summary |
||
(16 intermediate revisions by 3 users not shown) | |||
Line 9: | Line 9: | ||
! Name | ! Name | ||
! Comments | ! Comments | ||
|- | |||
| 0x1EF00000 | |||
| 0x10400000 | |||
| 4 | |||
| Hardware ID | |||
| Bit2: new model | |||
|- | |- | ||
| 0x1EF00004 | | 0x1EF00004 | ||
Line 32: | Line 38: | ||
| 4 | | 4 | ||
| VRAM bank control | | VRAM bank control | ||
| Bits 8-11 = bank[i] disabled; other bits are unused | | Bits 8-11 = bank[i] disabled; other bits are unused. | ||
|- | |- | ||
| 0x1EF00034 | | 0x1EF00034 | ||
Line 38: | Line 44: | ||
| 4 | | 4 | ||
| GPU Busy | | GPU Busy | ||
| | | Bit26 = PSC0, bit27 = PSC1, Bit30 = PPF, Bit31 = P3D | ||
|- | |- | ||
| 0x1EF00050 | | 0x1EF00050 | ||
Line 134: | Line 140: | ||
Memory fills are used to initialize buffers in memory with a given value, similar to memset. A memory fill is triggered by setting bit0 in the control register. Doing so aborts any running memory fills on that filling unit. Upon completion, the hardware unsets bit0 and sets bit1 and fires interrupt PSC0. | Memory fills are used to initialize buffers in memory with a given value, similar to memset. A memory fill is triggered by setting bit0 in the control register. Doing so aborts any running memory fills on that filling unit. Upon completion, the hardware unsets bit0 and sets bit1 and fires interrupt PSC0. | ||
The addresses must not be part of FCRAM. | |||
These registers are used by [[GSP Shared Memory#GX SetMemoryFill|GX SetMemoryFill]]. | These registers are used by [[GSP Shared Memory#GX SetMemoryFill|GX SetMemoryFill]]. | ||
Line 145: | Line 153: | ||
To make sense of these values, the 3DS must be held in a way, so that the bottom screen is in the left hand, and the top screen is in the right hand, and that way the first pixel will be in the top-left corner, as it should be. If the 3DS is held normally, the first pixel is in the bottom-left corner. | To make sense of these values, the 3DS must be held in a way, so that the bottom screen is in the left hand, and the top screen is in the right hand, and that way the first pixel will be in the top-left corner, as it should be. If the 3DS is held normally, the first pixel is in the bottom-left corner. | ||
All pixel and scanline timing values are 12bits, unless noted. This also applies to those fields where two u16 are combined into one register. Each u16 field is only 12bits in size. | All pixel and scanline timing values are 12bits, unless noted. This also applies to those fields where two u16 are combined into one register. Each u16 field is only 12bits in size. timin | ||
The horizontal timing parameter order is as follows (values may overflow through HTotal register value): | |||
0x10 < 0x14 <= 0x60.LO <= 0x04 <= 0x60.HI <= 0x08 <= 0x0C <= 0x10 | |||
0x18 <= 0x60.LO | |||
Timing starts from HCount == 0, then each absolute value in the beforementioned register chain triggers when HCount == register, latching the primitive display controller into a new mode. | |||
There is an inherent latch order, where if two simultenaous events occur, one event wins over another. | |||
Known latched modes (in order): | |||
- HSync (triggers a line to the LCD to move to the next line) | |||
- Back porch (area between HSync and border being displayed, no pixels pushed, min 16 pixel clocks, otherwise the screen gets glitchy) | |||
- Left border start (no image data is being displayed, just a configurable solid color) | |||
- Image start (pixel data is being DMA'd from video memory or main RAM) | |||
- Right border start/Image end (border color is being displayed after the main image) | |||
- Unknown synchronization (supposed to be probably right border end, but this mode seems to be broken or not do anything) | |||
- Front porch (no pixels pushed, 68 clock min, otherwise the screen doesn't sync properly, and really glitches out) | |||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
Line 159: | Line 183: | ||
|- | |- | ||
| 0x04 | | 0x04 | ||
| | | HStart | ||
| | | Determines when the image is going to be displayed in the visible region (register 0x60). | ||
|- | |- | ||
| 0x08 | | 0x08 | ||
| ? | | HBR | ||
| | | Right border start(?). Does nothing. | ||
While this register seems to have no impact on the image whatsoever, it still has to be set to a valid value. | |||
| | |||
|- | |- | ||
| 0x0C | | 0x0C | ||
| | | HPF | ||
| | | Front porch. The image is blanked during this period, and no pixels are pushed to the LCD. | ||
Unknown why, but a single dot of red is displayed before entering this mode. | |||
|- | |- | ||
| 0x10 | | 0x10 | ||
| | | HSync | ||
| | | Triggers a HSync pulse. | ||
Based on behavior, this needs to last at least a pixel clock for the LCD to register the sync. | |||
|- | |- | ||
| 0x14 | | 0x14 | ||
| | | HPB | ||
| | | Back porch? Has to be at least one bigger than HSync, otherwise HSync never triggers. | ||
The display is blank, and the LCD displays nothing in this period (doesn't push pixels). | |||
|- | |- | ||
| 0x18 | | 0x18 | ||
| | | HBL | ||
| | | Left border trigger treshold. Enables pushing pixels to the display. | ||
If this value is smaller than the back porch, then the back porch period will be zero, and the border will be immediately displayed upon entering the back porch period. | |||
Can be lower than HSync, as the back porch is what takes the controller out of HSync. | |||
Must be <= HDisp start (reg 0x60 low u16), otherwise no pixels will be pushed due to a glitched state. | |||
|- | |- | ||
| 0x1C | | 0x1C | ||
Line 205: | Line 233: | ||
|- | |- | ||
| 0x20 | | 0x20 | ||
| | | low u16: ??? | ||
high u16: ??? | |||
| | | ??? | ||
??? | |||
|- | |- | ||
| 0x24 | | 0x24 | ||
Line 220: | Line 243: | ||
VClock = PClock / (HTotal + 1) / (VTotal + 1) | VClock = PClock / (HTotal + 1) / (VTotal + 1) | ||
Setting this to 494 lowers framerate to about 50.040660858 Hz ((268111856 / 24) / ( | Setting this to 494 lowers framerate to about 50.040660858 Hz ((268111856 / 24) / (450 + 1) / (494 + 1)). | ||
|- | |- | ||
| 0x28 | | 0x28 | ||
Line 275: | Line 298: | ||
| 0x5C | | 0x5C | ||
| ??? | | ??? | ||
| low u16: | | low u16: Image width (including some offset?) | ||
high u16: | high u16: Image height??? (seems to be unused) | ||
|- | |- | ||
| 0x60 | | 0x60 | ||
| | | HDisp | ||
| low u16: | | low u16: Image start (border --> pixel data) | ||
high u16: | high u16: Image end (pixel data --> border) | ||
|- | |- | ||
| 0x64 | | 0x64 | ||
Line 297: | Line 320: | ||
|- | |- | ||
| 0x70 | | 0x70 | ||
| Framebuffer format | | Framebuffer format and other settings | ||
| | | See [[#Framebuffer_format|framebuffer format]] | ||
|- | |- | ||
| 0x74 | | 0x74 | ||
Line 354: | Line 377: | ||
|- | |- | ||
| 2-0 | | 2-0 | ||
| Color format | | [[#Framebuffer_color_formats|Color format]] | ||
|- | |- | ||
| 5-4 | | 5-4 | ||
| Framebuffer scanline output mode ( | | Framebuffer interlacing mode | ||
0 - A (no interlacing) | |||
1 - AA (scanline doubling) | |||
2 - AB (interlace enable) | |||
3 - BA (same as above, but the fields are inverted) | |||
In AB and BA interlace modes, a scanline from each framebuffer is output in an alternating manner. In AB mode, Framebuffer A is output on the frist display scanline. Similarly, in BA mode, Framebuffer B gets output to the first display scanline. | |||
The way AB and BA modes work, is that a scanline is output, the framebuffer stride value is added to the internal scanline pointer value, and the other framebuffer is selected. And this alternates until the end of the draw region. | |||
AA interlacing works like AB interlacing, except both internal framebuffer pointers are set to the Framebuffer A pointer value. | |||
In A mode (no interlacing), it doesn't switch to the other framebuffer at the end of outpuitting a scanline to the display. | |||
Bottom screen has this set to 0 (A mode, no interlacing) at all times. | |||
Top screen uses AB interlacing in 3D mode (with 3D slider enabled), and A mode (no interlacing) in 2D mode. | |||
|- | |- | ||
| 6 | | 6 | ||
| | | Alternative pixel output mode* | ||
|- | |- | ||
| 7 | | 7 | ||
Line 379: | Line 406: | ||
|- | |- | ||
| 9-8 | | 9-8 | ||
| | | DMA size | ||
0 - 4 FCRAM words (32 bytes) | |||
1 - 8 FCRAM words (64 bytes) | |||
2 - 16 FCRAM words (128 bytes) | |||
3 - ??? | |||
FCRAM doesn't support DMA size 3, as it can only burst up to 16 words (128 bytes), and will show a black screen instead. | |||
|- | |- | ||
| | | 31-16 | ||
| | | Unknown | ||
|} | |} | ||
* The weird thing about | |||
<nowiki>*</nowiki> The weird thing about bit6, is that it works different between the bottom and top LCD. On the bottom LCD, it doubles the number of outputted pixels (so the same pixel is outputted twice, effectively doing pixel/column doubling). However on the top screen, it does scanline doubling instead. | |||
Most likely the top screen receives two pixels at once per clock unit, outputting two scanlines simultaneously. | |||
On a 2DS, it seems to have no effect on the top part of the display, and on the bottom screen it just shifts the framebuffer to the right two pixels. | On a 2DS, it seems to have no effect on the top part of the display, and on the bottom screen it just shifts the framebuffer to the right two pixels. | ||
GSP module only allows the LCD stereoscopy (3D) to be enabled when bit5=1 and bit6=0 here. When GSP module updates this register, GSP module will automatically disable the stereoscopy if those bits are not set for enabling stereoscopy. | |||
When both interlacing and alternative mode is disabled (bit6=0), the full resolution of the top screen (240x800) can be utilized if the PDC registers are updated to accomodate this higher resolution. GSP contains tables for this mode (gsp mode == 1). GSP automatically applies this mode if both bit5 and bit6 are cleared. This is also the default, and the only valid mode for the bottom screen in userland. | |||
If only AB interlacing is enabled (bit5=1, bit6=0), gsp detects this as a request to switch to 3D mode (gsp mode == 2), and enables the parallax barrier. | |||
It's unknown how to control this, but some other PDC registers control if interlacing should be done by true interleaving (both framebuffers are treated as 240x400), or by skipping lines (both framebuffers are treated as 240x800). | |||
If only | If only alternative mode is enabled (bit5=0, bit6=1), gsp detects it as a request to switch back to 2D mode for the top screen (gsp mode == 0). This is also the default mode for the top screen. | ||
Both interlacing and scan doubling can't be enabled in usermode, but it works as expected in baremetal. | Both interlacing and scan doubling can't be enabled in usermode, but it works as expected in baremetal. | ||
Line 466: | Line 503: | ||
These registers are used by [[GSP_Shared_Memory|GX command]] 3 and 4. For cmd4, *0x1EF00C18 |= 1 is used instead of just writing value 1. The DisplayTransfer registers are only used if bit 3 of the flags is unset and ignored otherwise. The TextureCopy registers are likewise only used if bit 3 is set, and ignored otherwise. | These registers are used by [[GSP_Shared_Memory|GX command]] 3 and 4. For cmd4, *0x1EF00C18 |= 1 is used instead of just writing value 1. The DisplayTransfer registers are only used if bit 3 of the flags is unset and ignored otherwise. The TextureCopy registers are likewise only used if bit 3 is set, and ignored otherwise. | ||
The minimum supported dimension for output is 64x64, anything lower will hang the engine. | |||
==== Flags Register - 0x1EF00C10 ==== | ==== Flags Register - 0x1EF00C10 ==== | ||
Line 520: | Line 559: | ||
=== TextureCopy === | === TextureCopy === | ||
When bit 3 of the control register is set, the hardware performs a TextureCopy-mode transfer | When bit 3 of the control register is set, the hardware performs a TextureCopy-mode transfer: no format conversions are done, instead a raw data copy is performed from the source to the destination, with a configurable gap between lines. All bits of the control register are ignored, except for input/output dimensions, which are used for line width and gap, and bit 2, which must be set when gaps are used. | ||
The total amount of bytes to copy is specified in the size register, the hardware loops reading lines from the input and writing them to the output until this amount is copied. The gap specifies the number of bytes to skip after each line read (a gap of 0 results in a contiguous read). Gaps do not count towards the total size of the transfer. | |||
When setting line width and gap they must be divided by 2 (it can be thought as the calculation being done in bits, and the values being stripped of their lower 4 bits for the alignment). For example, if the left half of a 32x32 RGB8 texture is to be copied, the parameters will be: | |||
line width = (16 * 24) >> 4 = 24 | |||
gap = line width | |||
size = 16 * 32 * 3 = 1536 | |||
By correctly calculating the input and output gap sizes it is possible to use this functionality to copy arbitrary sub-rectangles between differently-sized framebuffers or textures, which is one of its main uses over a regular no-conversion DisplayTransfer. When copying tiled textures/framebuffers it's important to remember that the contents of a tile are laid out sequentially in memory, and so this should be taken into account when calculating the transfer parameters. | By correctly calculating the input and output gap sizes it is possible to use this functionality to copy arbitrary sub-rectangles between differently-sized framebuffers or textures, which is one of its main uses over a regular no-conversion DisplayTransfer. When copying tiled textures/framebuffers it's important to remember that the contents of a tile are laid out sequentially in memory, and so this should be taken into account when calculating the transfer parameters. | ||
Specifying invalid/junk values for the TextureCopy dimensions can result in the GPU hanging while attempting to process this TextureCopy. | Specifying invalid/junk values for the TextureCopy dimensions can result in the GPU hanging while attempting to process this TextureCopy. For instance, when in contiguous mode the size must be at least 16; when in gap mode, the size must be at least 192, and the line width must not be 0. | ||
== Command List == | == Command List == |