Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[QUESTION] SDL2 redraw #641

Open
codeservice opened this issue Aug 16, 2019 · 8 comments
Open

[QUESTION] SDL2 redraw #641

codeservice opened this issue Aug 16, 2019 · 8 comments
Assignees
Labels

Comments

@codeservice
Copy link
Contributor

I still have issues with GC blocking when I am using DirectRender. If I remove(comment) redrawing event after building cache it works well (cpp code included below). This redrawing event force to trigger DirectRender too and if I have animation based on dynamic looping parameters it speedup DirectRender animation. This can be fixed by moving animation looping parametrs to frame render event but I can't fix GC blocking error. My question is this redrawing event after building cache really necessary? After commenting this code I don't see big difference in graphics rendering and this fix GC error with fast animation looping issues.

void StartAnimation()
{
...
// Kill some time
if (waitMs>0)
{
AutoGCBlocking block;
if (sgSDLFrame->mStage->BuildCache())
{
//Event redraw(etRedraw);
//sgSDLFrame->ProcessEvent(redraw);
}
else
{
...

@hughsando
Copy link
Member

You are right - it should not be blocking while the ProcessEvent call is made, the logic needs to be split up a bit.

@codeservice
Copy link
Contributor Author

So it means we need to force redraw between frame draws if we have extra time before next wake. This behavior unique to SDL only. I don’t see something similar on mobile. I have case when I move 2D surface on top of DirectRender 3D scene and this surface moving force to redraw event which force DirectRender event trigger faster than frame rate and 3D animation looks accelerated. This effect observable only on SDL, mobile fine. It fixable by moving animation parameters to frame enter event. Only problem we have different behavior on mobile and SDL.

@hughsando
Copy link
Member

This is a tricky one, and designed to help with a low (or zero) frame rate. Say you are running an animation at 12fps, so you set the stage frameRate to 12. Or even an even driven app, so you set the frame rate to zero. But also, you have a mouse cursor drawn in graphics, or a text input box where the user types. If the user moves the mouse or types text, you want the display to update more that 12 (or zero) fps. So you want to peg your animation rate to either the absolute clock (or a quantized version of it) or the ENTER_FRAME event, but not the onRender event.
There might be an issue with what is considered dirty - especially when custom renders are considered. But maybe it is the moving surface - is it in response to a mouse event?

I can see opportunistically rebuilding the cache, but then not doing a render until the time runs out might be a good thing, but generally if the developer has changed something then showing the user sooner is generally a good thing.
If you are changing things in an onRender event, then I guess you are going to get full speed updates. The alternative here would be to set some state variable and apply it on the enter_frame event.

@codeservice
Copy link
Contributor Author

But maybe it is the moving surface - is it in response to a mouse event?
yes it’s window with text info and buttons, can be moved by mouse or touch events. When I move this window on screen, 3D animation accelerating, like fast forward video.

I agree it’s reasonable for low FPS rate apps. On 60 FPS, redrawing doesn’t make much difference. Thinking, maybe definition of low rate app can be as less than 24 frames per second and code in this case can look like:
if (waitMs>0)
{
AutoGCBlocking block;
if (sgSDLFrame->mStage->BuildCache())
{
If(FPSvalue<=24) {
block.Close();
Event redraw(etRedraw);
sgSDLFrame->ProcessEvent(redraw);
}
}
...

Or maybe I am to overthinking this and need to move animation parameters to frame enter event as suggested. Code going to look a bit strange in this case. I need to place 3D scene view render method into DirectRender and parameters for rendering scene apart into frame enter event. And this make sense only for desktop apps based on SDL. It something what hard to explain for developers, why I am doing it this in so tricky way :)

@hughsando
Copy link
Member

It depends on your animation to some extent, but is usually makes sense to decouple your animation rate from your render rate. eg, what if the system is very slow? Does this mean the animation runs slower vs skipping frames?
You can still update in the onRender - but use (timer.stamp()-t0)*fps, rather that frame++ as your counter. This could also help with the naturally different speeds of systems.
We could also look at a global setting to disable this, or perhaps a way of cancelling this particular event.
I have done quite a bit of work with 0fps on desktop, but not on mobile, so this is probably the difference.

@codeservice
Copy link
Contributor Author

codeservice commented Aug 19, 2019

what if the system is very slow?

By FPSvalue I had in mind stage.frameRate. I think this does not depend on how fast system respond on rendering. Low rate app can be detected when it less then stage.frameRate < 24.

Simplest onRender code I have, something like:
_plane.rotationY += 1;
_view.render();
I am using it for rotating single texture on screen. (timer.stamp()-t0)*fps probably going to complicate logic. When I move _plane.rotationY += 1 to ENTER_FRAME it works well.

We could also look at a global setting to disable this, or perhaps a way of cancelling this particular event.

This can work for me too:
if (waitMs>0)
{
AutoGCBlocking block;
if (sgSDLFrame->mStage->BuildCache())
{
#if SDL_FORCE_REDRAW
block.Close();
Event redraw(etRedraw);
sgSDLFrame->ProcessEvent(redraw);
#end
}
}
...

Which way best to proceed with this issue? For me stage.frameRate < 24 looks attractive. Dont know only how can I use this value on cpp side, dont see anywhere code for passing this parameter from stage.hx to cpp code. #if SDL_FORCE_REDRAW probably easiest.

@hughsando
Copy link
Member

By slow, I mean what if the the system takes 100ms to render? You will only get 10fps, and the plane will rotate more slowly (visually)

A traditional system would be like:

static var lastRender = 0.0;
function onRender()
{
   var now = haxe.Timer.stamp();
   var delta = Math.min(now-lastRender,0.250) * 24.0;
   t0 = now;

   _plane.rotationY += delta;
   //...

Which keeps the animation running at the same rate if the renders come in at 10fps or 100fps. It may even look better if you run at 60fps rather than 24 fps - the exception being if you have some frame-based drawings - but then I think to get the optimal smoothness you would need to do something more sophisticated again to take monitor refresh rate into account.
I will have a think about whether the even can easily be cancelled - otherwise a define to turn it off (NME_STRICT_FRAMERATE?) might be the go.

@codeservice
Copy link
Contributor Author

Adjustable looping parameters really cool technique. Require a bit more coding. For simplicity I am keeping drawing time reasonable in 0..1000/60 ms range. I need to use more time based rendering.
Parameter NME_STRICT_FRAMERATE can be helpful for keeping similarity with mobile and SDL onrender behavior. I think on mobile devices if drawing time longer then frame rate device skipping frames. Frequently can see these warnings on android simulator because rendering to slow for expected frame rate. Maybe possible make mobile render similar to desktop SDL, not sure if this can be done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants