Яндекс

Wednesday, November 30, 2016

Post filters

tab. It is the last stop for version 1.2 And it is very short stop overall.

Bloom

It was planned to add many various shader based post filters for GLideN64. However, due to lack of resources only Bloom was implemented for version 1.2 You may read more about it in "Bloom post filter" article. Bloom filter not changed since 1.2

Gamma correction

Version 1.2 has support for N64 gamma correction. However, that was done in a wrong way: as additional color transformation in fragment shader. From architectural point of view it means that gamma correction is performed by RDP. It is wrong because it is duty of N64 Video Interface. That wrong solution caused glitches in frame buffer emulation work, when previous gamma-corrected buffer blended with new one and picture quickly became overexposed. Thus that functionality was refactored, and gamma correction moved on its proper place as post-filter. I also added option to force gamma correction. You may use it if some game looks too dark for you.

On Screen Display

This new tab created for user-requested feature. Users asked me to implement on screen information about plugin's performance. On this tab you may select font and color of displayed message, which counters to show and where to show them. That is all.

Monday, November 28, 2016

Lets continue our excursion. Today it will be short. We will learn, what is new in

Texture Enhancement

As you know, GLideN64 adopted texture enhancement library from Glide64 project. Original library, GlideHQ, created by Hiroshi Morii aka KoolSmoky. It was ported to GlideN64 as GLideNHQ. I refactored some code, removed texture compression from original code, add support for OpenGL formats, add support for new filter xBRZ. GLideNHQ evolution continued after release of 1.2
New features:

Regarding texture packs: I made several fixes in that code, but all the functionality remained the same as with version 1.2 Font selection controls for on screen messages moved to new tab "On screen display", which will be introduced later.

Thursday, November 24, 2016

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:

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.

Options:

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.

Monday, November 21, 2016

Today we will continue to learn new features of upcoming Public Release

Now we will compare

Emulation panel

As you may notice, new version has more reach set of options.

Emulate mip-mapping

That important and hard to emulate feature is available since the first Public Release. Several issues with mip-mapping were found and fixed since that, so now it works even better.

Emulate noise

It was good before, so no major changes there.

Emulate fog

Do not worry, fog emulation is still there. However, it is not optional anymore. Now it is part of one very important feature, which works silently under the bonnet of GLideN64 engine and has no user handle. This feature has a long story, worth to tell it to interested emu fans:

Long time ago I told you a story about my fight with N64 color combiner, and how I successfully defeated that problem using magical beans shaders. Similar long story happened with N64 blending. N64 color blending is pretty much similar to OpenGL one. It also mixes input color with color in frame buffer using some blending factors. However, there are differences. If N64 combiner uses 2 cycle mode, blender has 2 cycles too. It is not the main problem though. The main problem is that blender can use two constant colors in blending equations, namely fog and blend colors. Fog color usually used to apply fog. However, it is not prohibited to use it for other purposes. Thus, it is possible to mix output from color combiner with constant colors, thus turning blender to additional stage of color combiner! Surely, many games use that possibility. I could not emulate such combine modes with Standard OpenGL blending. I would be glad to use magical shaders again, but unfortunately blending is a part of so-called OpenGL fixed functionality. It is prohibited to read value from frame buffer, blend it and write back using shaders. In other words, no blending with shaders!

There are GL extensions, which promise to allow shader based blending if some conditions met. Use of them could lead to incompatible hardly working solution. I disliked it. Standard OpenGL blender failed in each case where N64 blender used to combine colors. To fix it, I added special code in fragment shader, which performed necessary additional manipulation with color combiner output color. In fact, these were bunch of ugly hacks. That bunch had tendency to grow. When I met yet another problem, which required special support in code I said enough! I studied all details of N64 blender again and invented general solution to this problem. I wrote special shader program, which uses the same inputs and equations as in N64 blender and which does all mixing and blending except the final one: blending with buffer color. That final mix performed by standard GL blender, with no extensions. Result was wonderful. No more ugly hacks. Several long lasted issues instantly disappear (see #481 for example). Fog emulation is now part of the blender, and thus always enabled. The only drawback is additional load on graphics card, which is noticeable on some old mobile GPU. Thus, I left option to use fast inaccurate legacy blending, but this option is not available for desktop build. You may read more about new blending emulation in thread #970.

Enable Hardware lighting

This option enables per-pixel lighting calculation known as Phong shading. I already wroteabout it. It not changed since that time.

Enable shaders storage

This is new feature added by request from users of mobile version. Plugin uses shaders to emulate N64 color and alpha combine equations, as described here. When game uses new combiner, new shader program created. Shader programs compiled and linked on the fly. GLideN64 generates quite large and complex shadres. Shaders compilation on mobile devices can cause stuttering in gameplay. OpenGL allows to get binary representation of linked shader program. That binary data can be stored in a stream (file) and then restored later. When shaders storage option is enabled, plugin saves all shaders in a file. When user starts that game again, plugin loads all previously compiled shaders from that file and further gameplay goes smooth. Of course, if you will met new combiner, corresponding shader will be created on the fly and saved in the storage on exit.Note: binary representation of shader program depends on GPU and drivers version. Do not try to copy your shader storage to other device: it either will not work or will work improperly.

Use custom per-game settings

The meaning of that option remains the same, but content of custom settings file changed almost completely due to major changes in frame buffer emulation.

2D fixes

Original N64 2D graphics looks good in original resolution, but when you use hi-res output various glitches appear. So, the best way to get perfect 2D is to use original resolution. Set original scale factor to 1 and enjoy. If you playing 3D game, it will look poor in original low resolution. So if you want to get nice hi-res picture, and minimize glitches in 2D, pay attention on the following options.

Fix black lines between texrects

Enabling that option may help to remove black lines between adjacent textured rectangles. The problem and solution described in issue #450. If you see black lines between polygons, try "smart" option. Did not help? Try "force". Still not working? Sorry, there are games with broken 2D even in native resolution, see issue #936. We are working on it.

Example of black lines removal.

Render 2D in native resolution

This option enabled multi-pass rendering of 2D elements. The problem and solution described in this article and in thread #800. This feature greatly improves 2D in many games, but currently it is not the silver bullet to kill all 2D issues.

Saturday, November 19, 2016

As you know, GLideN64 is actively developed open source project. Source code modified almost daily. You may build current state at any moment, or download weekly WIP builds. Thus, you may ask: what is so important in new Public Release and how it will differ from WIPs?

Current Public version 1.2 released 6 July 2015. It was the last version funded by GLideN64 Crowd-funding Campaign Launched on Indiegogo. Since that I'm working on the project at my spare time. Of course, development slowed down. From the other side, open source attracting other resourceful developers to the project, who made many useful changes in code and helped me with ideas or advice. Thus, the work never stopped. Plugin constantly evolved and at some moment I started to feel that all these hundreds of changes deserve to be marked by a new milestone. This milestone is the new Public Release. This time there will be no private beta testing period. My current goal is to fix remaining regressions and clear some stuff. After that I will can say - new release is ready. New translation files also would be nice to get, but not must.

I am preparing set of articles explaining what is new in the upcoming release in compare with the old one. Since most of new features available via users options from user interface, let's compare GUI for both versions.
Note: new version will have new redesigned GUI, but it is more convenient to use current old-style one for comparison.

"Video" panel

Full screen resolution

It is the same.

Windowed resolution.

New feature: custom resolution. As before, you may select predefined windowed resolution from the list. If you need something special, select custom and set windows size in spin-box controls. On the screen shot I set window size to 800x460 to test widescreen mode in window.

Crop.

This is new feature made by users request. Its purpose is to remove black boarders, which many N64 games add around image. If you do not care about the black boarders, just skip explanation of that feature. ...
So, you want to finally get rid from these black boarders, which eat useful space on your screen. This feature is for you! It works as standard crop in graphics editors: cuts parts of the image from all sides and stretches the rest on entire screen. Simple like that. However, there are several things you need to know about that feature to use it properly.
Crop has two modes: auto and manual. In auto mode plugins tries to detect empty space and remove it. There are many ways to add black boarders. Auto detection method analyses scissor set by the game. Scissor is a standard tool in computer graphics. It defines rectangular area. All pixels outside that area automatically discarded. If scissor is less than frame buffer size, image will have empty boarders, which plugin can crop. Auto crop will fail if game uses other methods to make the boarders. In that case you need to use Manual mode. In that mode you need manually set width for horizontal and vertical areas to cut. Values you provide are numbers of pixels to crop in native resolution. That is, if game's original resolution is 320x240 and it uses borders with 12 pixels width, you need to set 12. That value will be scaled to get correct result in output resolution you selected. If you will set too large value to crop, you may lost useful part of the image. How to find the right value? Either try to increase crop one by one until black borders will be totally removed, or you may make screen shot in native resolution and find boarder width in a graphics editor.

Another note: crop works as post-processing filter. It works only if frame buffer emulation is enabled, as all other post-processing filters. Frame buffer passed to Video Interface, which applies crop if necessary and puts result on screen. I already explained, what Video Interface is and how it works. One important fact is that VI can add its own black borders and it usually adds one-two empty lines. These lines not removed with Crop. Keep it in mind.

Waverace in wide window with auto Crop

Internal Resolution.

This is new feature made by users request. In this version of GUI it is named as "Render at constant factor of native resolution". What it is for? When frame buffer emulation is disabled, plugin renders graphics in screen resolution defined by user. All graphics elements scaled to fit the screen. The scale defined as Screen Width / Original Width; Screen Height / Original Height. It is clear that if game uses 320x240 resolution, but screen has 1024x768 size, the scale will be fractional. There is a belief that fractional scale leads to additional glitches and it is right to use only those resolutions, which are integer factor of the original one. Thus users asked me to support render at constant factor of native resolution. It is not hard to do with frame buffer emulation. Frame buffer can have any internal resolution. Video Interface will scale it to user-defined screen resolution. Low-res buffer will be stretched to screen resolution, hi-res buffer will be shrunk to it. Also, you may set factor to 0. That will set that option off, so internal resolution will be the same as screen resolution.

Two important notes:

Factor 1 means "render in original resolution". This is most accurate emulation mode. Higher resolution often causes additional glitches, especially in 2D graphics. Thus, that mode is recommended for pure 2D games.

If you use Crop, part of the image will be cut and rest stretched to the screen. You may set high factor of native resolution and get internal resolution above the screen one. Thus, your frame buffer will still be larger than screen area after crop and resulted image quality can be better.

Normal rendering (left) VS native resolution (right)

Anti-aliasing

It remained the same. The only news is that AA is now supported on Android devices with GLES3.1 compatible GPU, thanks to Francisco Zurita efforts. If you want to use GLideN64 on Android, Mupen64Plus FZ is your choice.