Question

I'm writing a simple raycaster in C# using OpenTK. I want my view to refresh 60 times a second, so I have a timer calling my Render() function, that shows a texture on screen.

I want to use a recursive function to render my scene by dividing it into smaller rectangles and rendering each until rectangle size is 1px. My recursion writes colors of pixels to byte array, that I need to convert to a texture. Recursion is pretty slow, so I want to run it in a backgroud thread whenever my scene changes.

What is the correct way to synchronize threads so that one writes to texture array (it takes about a second), but the other thread reads it every 1/60 second and prints on screen?

    byte[, ,] texture;

recursion:

    public void RenderAdaptively(int top, int left, int width, int height)
    {
        Color color = getColor(top, left);
        for (int i = top; i < top + width + 1; i++)
        {
            for (int j = left; j < left + height; j++)
            {
                texture[i, j, 0] = color.R;
                texture[i, j, 1] = color.G;
                texture[i, j, 2] = color.B;
            }
        }

        int halfw = width / 2;
        int halfh = height / 2;
        int newwidth = width - halfw;
        int newheight = height - halfh;

        if (width > 1 && height > 1)
        {
            RenderAdaptively(top, left, halfw, halfh, false);
            RenderAdaptively(top + halfw, left + halfh, newwidth, newheight, false);
            RenderAdaptively(top, left + halfh, halfw, newheight, false);
            RenderAdaptively(top + halfw, left, newwidth, halfh, false);
        }
    }

in another thread:

    raycasting_texture = TexUtil.CreateRGBTexture(width, height, texture);
Était-ce utile?

La solution

You have several options to try, however I would do it like this:

  • have two buffers for storing the texture as a byte array, say 0 and 1,

  • do the texture computation in one buffer,

  • when it's done, signal it by setting a volatile int updated_buffer to the updated buffer index.

  • have the other thread read updated_buffer periodically, and keep a copy of its latest value. When that copy and the int are not in sync., update the copy and upload the texture to memory,

Note that this solution relies on several things:

  1. there are only two threads dealing with the byte array buffers,

  2. updated_buffer is only read by the (texture) consumer thread and written by the producer thread,

  3. and most importantly the texture upload is sensibly faster than the computation.

If #2 or #3 are broken, you will have to use a more stringent synchronization approach on the texture buffers, like mutexes, to make sure the texture buffers don't get overwritten when still being uploaded.

Finally, your recursive computation could get a slight boost by moving to an iteration below a certain threshold (say 8*8 pixel block), instead of going all the way down to 1px. In fact, doing it all iteratively should be faster (if done in a single thread on a single core), although it depends a lot on the algorithm for computing the pixels.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top