QNICE-FPGA icon indicating copy to clipboard operation
QNICE-FPGA copied to clipboard

Emulator: Optimize vga_refresh_rendering() for VGA_FONT_DATA and VGA_PALETTE_DATA

Open sy2002 opened this issue 3 years ago • 0 comments

Currently, when a program writes to the font data or palette data register vga_refresh_rendering(); is being called, which is heavily decreasing (if not even completely killing) performance in case a program changes for example the font graphics frequently.

Here is an idea of how to improve the performance on the native platform (WASM seems to support threads too, need to investigate):

  1. Add an optional parameter to vga_refresh_rendering(). If it is not specified then the function behaves like today. If it is specified, then it only changes certain characters on the screen. This saves tremendous computing power, as the font patterns can be only changed on pattern at a time and therefore it is known, which character is affected from the change.

That means something like this:

void vga_refresh_rendering(char filter = 0)
{
    for (int y = 0; y < screen_dy; y++)
        for (int x = 0; x < screen_dx; x++)
        {
            unsigned int vram_val = vram[y * screen_dx + x + vga_offs_display];
            if (!filter || (vram_val & 0x00FF == filter))  //ignore color, just filter for the char
               vga_render_to_pixelbuffer(x, y, vram_val);
}
  1. Make the whole re-rendering of the screen due to font changes multithreaded in the following sense:
  • FIFO buffer that contains jobs to be done for a worker thread (we already have a threadsafe FIFO in fifo.h and fifo.c). So this here
        case VGA_FONT_DATA:
            qnice_font[font_addr & 0x0FFF] = value;
            vga_refresh_rendering();
            break;

would be replaced by something like this here (pseudo-code):

        case VGA_FONT_DATA:
            qnice_font[font_addr & 0x0FFF] = value;
            add_to_refresh_fifo(font_addr); //is font_addr equal to the character we need to filter for?
            break;
  • Worker thread takes jobs from the fifo and runs vga_refresh_rendering(filter_value_pulled_from_fifo).

  • The worker thread creates a race condition, since it is writing to the VRAM in parallel to other threads who are writing to the VRAM. But this race condition is completely harmless and a human will notice a slight flicker - if at all.

  • P.S. Is & 0x0FFF right anyway? This would imply 12bit color instead of 15bit.

A similar thing might be done for the palette and palette changes.

As a test, we might use #ifdef EMULATOR in vga_circle.c to have a simplified version that does not rely on the scanline interrupt and/or scanlines in general, so that we can check, if the optimization works at all.

This issue blocks #17.

@MJoergen I can support you with all of this, if you want, but as I am still on my boat, you might be faster :-)

sy2002 avatar Sep 04 '20 00:09 sy2002