Thursday, November 24, 2016

New Public Release. Part III

Time to see, what is new in

Frame buffer emulation

Buffer swap mode

This is new option. It controls how often rendered frame buffer will be copied to screen. N64 Video Interface updates screen on each Video Interrupt system call, which happens 50 times per seconds for PAL and 60 for NTSC. Frame buffer data usually updated not as often. For example, NTSC version of Zelda updates frame buffer 20 times per second (20 frames per second or 20 FPS). It looks reasonable to copy frame buffer to screen not on every Video Interrupt, but only when new buffer is ready.

PR 1.2 has only one strategy for buffer swap, which is based on some heuristic. Later it was found that the heuristic not always works good. New heuristics were invented, but they also failed in some cases. Finally I decided to follow N64 Video Interface behavior: copy frame buffer to screen on every Video Interrupt. That solved all known issues with video update. Thus, this option is default one for desktop builds and you hardly will ever need to change it.

That mode increases load on GPU. It is not noticeable on desktop graphics cards, but mobile users began to complain.  Thus, by their request another two buffer swap modes added:

  • on VI origin change: swap when address of buffer to display changed
  • on Color buffer change: swap if plugin knows that buffer content changed
These modes are modifications of heuristic, used in version 1.2 If you have performance issues, try to change buffer swap mode.

Emulate N64 depth compare

That feature described in 'Depth buffer emulation' article. I fixed few issues related to it, but in general it is the same experimental shader based depth compare, as in version 1.2 It still has experimental status and is not recommended for every game. However, several games will not work correctly without it.

Copy auxiliary color buffer to RDRAM

This is another experimental feature. GLideN64 developer purplemarshmallow noticed that some weird issues can be fixed if an auxiliary color buffer created by game will be copied to RDRAM right after switch to another buffer. Example: Mario Artist. purplemarshmallow implemented that feature. Unfortunately, it often brings additional glitches and currently has experimental status. Use on your own risk.

Buffer read/write with emulator help

This is another very promising experimental feature. The problem described in 'Emulation of CPU based frame buffer effects' article. In short: plugin needs to copy color and depth buffer content from video memory to to N64 RDRAM to emulate frame buffer effects. Plugin does not know when N64 CPU will need these buffers, so plugin copies them each frame. That leads to overheads and, sometimes, to crashes. Also, sometimes N64 CPU renders something over frame buffer prepared by RDP. Plugin needs to render frame buffer in RDRAM as texture over its frame buffer to not lose that data. Since plugin does not know, when CPU modified the buffer, plugin need to copy buffer from RDRAM each frame. That often causes garbage on screen.

Developers of 1964 emulator designed an extension for original Zilmar's plugin specifications. This extension is named FBInfo. Plugin provides emulator few new callback functions, which emulator uses to notify the plugin that CPU is about read or write data in frame or depth buffers. This extension, being properly implemented, would help plugin greatly. Plugin could read data from video memory only when necessary and only necessary part of it. Plugin could copy from RDRAM only those pixels, which were modified by CPU.

GLideN64 implements FBInfo extension, strictly following the specifications. Unfortunately, support of FBInfo on emulators side is far from perfect. You may read the whole story in this feature request #808. FBInfo currently supported by three emulators: 1964, Mupen64 and mupen64plus. 1964 implementation does not follow FBInfo specification (sic!), so it works, but slow. Mupen64 supports FBInfo by default, and the implementation follows FBInfo specification. Some games work wonderful with it. Unfortunately, Mupen64 misses some buffers modifications and does not inform plugin about them. This leads to glitches. The worst situation with mupen64plus. FBInfo functionality is heavily broken in it, and not recommended to use.

  • Do not use emulator help. It disables FBInfo even if it is supported by emulator. Set it if FBInfo does not work properly.
  • Read color buffer by chunks. When enabled, plugin follows FBInfo specification: "Notify the dll that the frame buffer memory is beening read at the given address. ... DLL should copy 4KB block content back to RDRAM frame buffer." Plugin will read only chunks of data, explicitly requested by emulator. It may reduce overheads if only few 4KB chunks have to be read. If CPU wants to modify whole buffer, read by chunks will be much slower. Since CPU usually needs the whole color buffer, that option is off by default.
  • Read depth buffer by chunks. The same as for color buffer. However, CPU seldom need to read the whole depth buffer. Usually it needs just few values to probe. Thus, depth buffer read by chunks is default.

Buffer read/write without emulator help

If FBInfo not supported by your emulator, or works incorrect, you may need to use force buffer read/write methods. If you do not remember, why buffer copy is necessary, read again 'Emulation of CPU based frame buffer effects' article.

Copy color buffer to RDRAM

Version 1.2 copies color buffer in sync mode. That is, plugin waits when all buffer data copied from video memory to conventional one. It guarantees that we copy actual frame buffer to RDRAM. Sync copy is slow and not always necessary. For example, frame buffer copy often used for TV monitor effect. TV shows part of the displayed picture. We can use asynchronous buffer reads for such effects. In async read mode plugin asks video card for data, but not waiting the result. Rendering process continues, and video driver performs data copy in background. Next frame the data will be ready for instant access. This data is not for current frame, but for previous one. For TV effect it is not important if it will display the picture with one frame lag. Actually, there are not so many games, which require sync color buffer reads. Thus, in new version async mode is default.

Copy depth buffer to RDRAM

Everything said about synchronous color buffer copy is true for depth buffer copy. Unfortunately, async read does not work for depth buffers. It is possible to read depth buffer asynchronously, but CPU does not recognize that data. CPU needs depth buffer data for the current frame exactly. Again, sync read is slow, especially for buffers above 320x240. When game uses 640x480 internal resolution, depth buffer read causes noticeable slowdown. Thus, I had to adopt my old technology from Glide64 times: software depth buffer render. That dusty code outperforms read from video memory in most of cases (if not in all). Thus, software render is default mode for depth buffer copy in new version.

Render frame buffer as texture

That option enables render data, prepared by N64 CPU, from RDRAM to video frame buffer. It was internally rewritten since version 1.2, but from users point of view it is the same.

Detect CPU writes to the frame buffer

Version 1.2 has that option to correctly emulate games, where CPU can suddenly take rendering on itself, bypassing the RDP. purplemarshmallow found a way to automatically detect such cases, so the option became redundant.

Frame buffer validity check method

Frame buffer validity is most serious problem in hardware frame buffer emulation. The problem described in "Frame buffer emulation. Part I." article. Version 1.2 uses several methods to check frame buffer validity and user can choose, which works better. purplemarshmallow made a large investigation of situations where these methods are applicable and efficient. The code was refactored and now it works transparently to user.


  1. When does the plugin come out I have issues with the most hi-res texture packs, so I am happy to get this very soon.

  2. Download WIP build and test it with your hi-res texture packs. Texture pack support hardly will change to release date.