Sign in to follow this  
solinent

SDL_surface and multiple threads

Recommended Posts

I'm trying to make a raytracer. So far, it works for phong shading and no other features (it doesn't do shadows yet). However, it takes 500ms to render one scene. So, so far, I've applied optimizations to use SSE, and that brought it down to 300 (not more because I don't use a w component in my calculations). Finally, I decided to make it multi-threaded. This is obvious and easy to implement in raytracing. My paticular thing uses something of the following code:
raytrace () {
 foreach (pixel in width) {
  foreach (pixel in height) {
   //do calculations
   putpixel (format, finalpixelcolor, x, y)
  }
 }
}
Now, all I have to do is make it parallel. So I decided that one thread would render every other line, and create a static variable to determine how many times raytrace has been called. So
raytrace () {
 static stride=-1; stride++;
 foreach (pixel in width) {
  foreach (x=stride;x<height;x+=2) {
   //do calculations
   putpixel (format, finalpixelcolor, x, y)
  }
 }
}
When I use multiple threads, it just simply doesn't work. If I have a HWSURFACE, then it gives me the first call, but the second thread returns only half of the pixels it requries (about). SWSURFACE only returns the results from the first thread. So, how should I go about this? Should I create a buffer of final pixel color's for one thread, and pixel colors for the other, and then stitch them together later into a surface? Or is there a more SDL way to do this?

Share this post


Link to post
Share on other sites
Quote:
According to the SDL docs, there is a bug on Win32 where calling drawing functions from multiple threads is unstable.


putpixel isn't *really* a drawing function, if called on a software surface you are effectively only writing to memory.

@OP:

To use a static variable there you would need locking.

The way I did it was to make use of the SDL event queue, which is thread safe. I tell each thread to render a sub-rectangle of the full scene. Each thread allocates its own surface and fills it according to the sub-rectangle. When it is done, it uses SDL_PushEvent to put a SDL_UserEvent on the queue. The "main" thread simply calls SDL_WaitEvent, and waits for all the threads to complete drawing a frame before blitting all the surfaces to the screen.

500ms is nothing. Wait until you start writing all those really fancy effects [grin].

Share this post


Link to post
Share on other sites
Yeah, I know 500ms is nothing, but I realized that the majority of it is in the ray-sphere intersection code, and I wanted to get that lower before I started adding effects into it.

Heh, I'll look at both of your solutions.

A simple solution (since I don't care about the time it takes to draw to the screen, I'm just worried about the raw time), is that I draw to a buffer stored in memory.

So like this:

pixel[HEIGHT][WIDTH]

then in the loop, I would have

pixel[y][x] = phongshade();

and then draw the array later.

However, this doesn't seem to work at all.

So, now my question is how do I make this stuff accessible to both threads? I'm gonna debug my program more though, I'm not sure it even gets to try and access the first thread.

EDIT:

I see the problem now, the second thread ends early. Is this because I'm using the same function for both threads?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this