Register    Login    Forum    Search    FAQ

Board index » Everything




Post new topic Reply to topic  [ 5 posts ] 
Author Message
 Post subject: Design suggestions?
 Post Posted: September 3rd, 2015, 11:37 pm 
 

Joined: February 28th, 2013, 3:23 am
Posts: 2842
Location: Oklahoma, United States
In practicing SSE, I've decided to make some image filters, blending and lighten and so on. I'm having troubles deciding how I should go about implementing them. I tried a few different methods, but keep running into limitations with each.

Storing a surface in the filter class: The idea was I have the surface stored int he image filter class, and call one of the functions to manipulate the surface. The problem I had was that storing the manipulated pixels back on to the surface became cumulative. So each successive pass for each frame made the pixels brighter and brighter for instance when calling the Lighten function.

Passing a surface to the filter: The idea was that I could pass a source surface to the filter, and store the result in the filter's surface in the Go function, then call the filter.draw function in the ComposeFrame function of Game. The problem with this is the size of the filter's surface would have to match the surface being passed in. So the filter's surface would have to be resized for each different surface I wanted to pass through the filter. This would be slow always allocating and deallocating memory.

Passing a surface through the filter: There were two options here, one would have the same problem as storing a surface in the filter, where storing the converted pixels back onto the source surface would accumulate the result each frame. The second option was to just have the filter draw directly to the backbuffer, which provides the result I'm looking for, but doesn't feel right.

Passing a filter to a surface: What I would like is to have a filter be a class, where I just pass in the filter to the surfaces draw function, and then the surface will call the fitlers' Apply function and the surface will be responsible for putting the pixels on the back buffer and the filter will just work with the pixels passed to it. The problem is each filter needs a different set of inputs, so I'm not sure if this is possible. If I don't inherit from a base class, I would have to overload the Surface::Draw function for each type of filter I create.

Any suggestions?

_________________
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com


Top 
 Profile  
Reply with quote  
 Post subject: Re: Design suggestions?
 Post Posted: September 4th, 2015, 3:31 pm 
 

Joined: February 28th, 2013, 3:23 am
Posts: 2842
Location: Oklahoma, United States
A nagging thought keeps popping in my head as possible solutions.

First thought is to create a "scratch pad" of equal size for each surface.

Second thought is to create just one scratch pad, a memory pool if you will, and just store the address of where in the pool that surface's data is located.

In either case, I would need double the memory requirements as before. The first solution might be the easiest to manage though.

Third though is to take the memory pool idea and just reuse the same space, making draw calls just after each filter has been applied, meaning before working with the next surface I draw the result of each filter. The pool would probably just be a second backbuffer.

The benefits of course are not having to allocate/deallocate each frame or call to a surface's draw function. This is probably close to what is done in games anyway. You create a texture, upload to video card, create another texture that DirectX renders to, then you take that texture perform your filtering, then render to the back buffer, then flip or move to the next item to be rendered.

_________________
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com


Top 
 Profile  
Reply with quote  
 Post subject: Re: Design suggestions?
 Post Posted: September 5th, 2015, 1:15 am 
Site Admin
User avatar

Joined: December 31st, 2011, 4:53 pm
Posts: 3484
Location: Japan
My solution would be to use a std::function object pass your filter in. The problem in which each filter needs a different set of inputs can be solved with std::bind.

The idea in which the surface will be responsible for putting the pixels on the back buffer and the filter will just work with the pixels passed to it will probably sacrifice performance. You call the filter's process() method and pass it a ref& to the surface and it accesses the surface's buffer directly.

_________________
Chili


Top 
 Profile  
Reply with quote  
 Post subject: Re: Design suggestions?
 Post Posted: September 6th, 2015, 8:09 pm 
 

Joined: February 28th, 2013, 3:23 am
Posts: 2842
Location: Oklahoma, United States
chili wrote:
My solution would be to use a std::function object pass your filter in. The problem in which each filter needs a different set of inputs can be solved with std::bind.


I've a little experience using packed parameters and variadic templates thanks to cameron's event class. Nice to know std::bind seems to do the decay work for you. It did cross my mind to use variadic templates, but was a merely a fleeting thought. I'm not keen on recursively calling functions, and I haven't fully worked out how to do what bind does, but then again, I didn't know about std::bind. I'll have to give it a go.

chili wrote:
The idea in which the surface will be responsible for putting the pixels on the back buffer and the filter will just work with the pixels passed to it will probably sacrifice performance. You call the filter's process() method and pass it a ref& to the surface and it accesses the surface's buffer directly.


Well damn. The biggest reason for wanting to use a common function to draw from is to keep code redundancy down. There's clipping of sprites to screen edges, then there's handling edge cases with SSE. I really didn't want to have to duplicate those bits for each filter. Then again, I could clip in the surfaces draw call, and pass a clip rect to the filter.

Something like:
Code:
filter.Process(const UINT X, const UINT Y, const RECT &clip, const UINT SurfaceWidth, D3DCOLOR *const SourceSurface, D3DGraphics &gfx);


X and Y are the position to start drawing.
clip would be if the sprite is off screen or larger than back buffer.
SurfaceWidth would be the pitch of the surface in case the width of clip is different.
SourceSurface would be the surfaces' surface or buffer of pixels

the destination would of course be the back buffer which can be gotten from a gfx.getbuffer.

The edge cases and unaligned pixels I think I'll just handle using unaligned loads and stores, my brain hurts too much to constantly figure out the shifting, shuffling and masking otherwise.

_________________
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com


Top 
 Profile  
Reply with quote  
 Post subject: Re: Design suggestions?
 Post Posted: September 6th, 2015, 8:53 pm 
 

Joined: June 26th, 2012, 5:38 pm
Posts: 765
Location: USA
An alternative to std::bind is to store the wrap your function call in a lambda. I've found this yields better performance, but lacks placeholders.

Code:
std::function function;
template<class O, typename Func, typename... Args> Function(O& o, Func(O::*func), Args&&... args)
{
function = [&o, func, &args...]()->RT
{
return (RT)((o.*func)(std::forward<Args>(args)...));
};
}


A faster way is to use placement new over operator=

_________________
Computer too slow? Consider running a VM on your toaster.


Top 
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
 
Post new topic Reply to topic  [ 5 posts ] 

Board index » Everything


 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
cron