Welcome, Guest. Please login or register.

Author Topic: Warp3d synchro/double-triply bufferging  (Read 18585 times)

Description:

0 Members and 1 Guest are viewing this topic.

Offline kas1eTopic starter

Warp3d synchro/double-triply bufferging
« on: February 11, 2005, 12:34:18 AM »
Hi 2 all. I have a lame question about syncro in warp3d. I using voodoo3/aos3.9/m68k and want to do some truecolor animation. So:

I draw 640x480x32bit picture on screen (this picture = 6 textures), and try to scroll on this picture some sprite (128x512x32) with transparency. So, if i just move sprite (witchout redrawing some areas (textures) of my backscreen) it work nice with WaitTOF() only. BUT. If i moving sprite, and trying redrawing part of backscreen (two 256x256 textures), (do it animation i mean), i have some bugs on screen. Not big bugs, but some UPpers areas of my screen is 'blinking'. If i drawing in 'low' part of screen, it is work fine.. I don't know what is it, maybe problem with WaitTOF() or need do it somethink else ..

Well, next, i read some docs (graphics/intuition/warp3ddev), and found some worlds about 'double buffering'. It is allow to me rendering all data to 'invisible' scren, and flip with 'main' screen. But i do not understand HOW it can be help me. If WaitTOF() can't do it good synchro, how buffer fliping can give me good synchro ?

So, if i understand correctly, double-buffering can solve my 'some blinking UPpears areas'. (i am right?) And as i reading, here is 2 ways for it :

1. ScreenBuffer (alloc/change/free).
2. ScrollVPort + WaitBOVP.

Well, i just to try this code (only for 'flip' picture from 'invisibli' part, to 'main' part):

// ... create screen/window/warp3d context ...

   vp=screen->ViewPort;

  // draw to 'invisibli' screen.
   W3D_SetDrawRegion(context,bm,480,&s);
   vp->RasInfo->RyOffset=0;
   ScrollVPort(vp);
   WaitBOVP(vp);
   W3D_SetScissor(context, &s);

   // draw my pict, to 'invisibli' buffer, and do it some wait.
   draw_pict(context,1.0f);
   Delay(10);

   // flip to 'main' screen
   W3D_SetDrawRegion(context,bm,0,&s);
   vp->RasInfo->RyOffset=0;
   ScrollVPort(vp);
   WaitBOVP(vp);
   W3D_SetScissor(context,&s);  


And nothink to happened .. Picture was drawing on 'invisibly' part, and can't flip.


Next, i try to use ScreenBuffers:

// creating 2 ScreenBuffer. 'main' and 'invisible'.

  if(!(buf1=AllocScreenBuffer(screen, NULL, SB_SCREEN_BITMAP)))
     { printf ("failed to allocate screenbuffer\n"); goto panic;};

  if(!(buf2=AllocScreenBuffer(screen, NULL, SB_SCREEN_BITMAP)))
     { printf ("failed to allocate screenbuffer2\n"); goto panic;};

// BitMap for Warp3d context creating
  buf1->sb_DBufInfo->dbi_SafeMessage.mn_ReplyPort = NULL;
  bm = buf1->sb_BitMap;

  context = W3D_CreateContextTags(&CError,
          W3D_CC_MODEID,       ModeID,
          W3D_CC_BITMAP,       bm,
          W3D_CC_YOFFSET,      0,
          W3D_CC_DRIVERTYPE,   W3D_DRIVER_BEST,
          W3D_CC_FAST,         TRUE,
          W3D_CC_DOUBLEHEIGHT, TRUE,
          TAG_DONE);


 // ... skip some setstates/etc ...

 for(i=250;i>0; i-=5)
    {
       ChangeScreenBuffer(screen,buf2);   // draw to invisible buffer
       Draw_Sprite(context,i);
       ChangeScreenBuffer(screen, buf1);  // flip ScreenBuffers.
    };

And agayn, i have not a good synchro ;(


Well, here is questions:

1. Where best way for work with synchro on warp3d. If anyone have some sources it is will be very good.

2. How do it normal hi-rez animation on warp3d.

Any docs/link/sources/talks/help will be very good.


sorry for poor english, hope anyone can help me with it, thanks.
 

Offline Karlos

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show only replies by Karlos
Re: Warp3d synchro/double-triply bufferging
« Reply #1 on: February 11, 2005, 12:44:53 AM »
First of all, stick with the ScreenBuffer based buffering. It's much less of a pain in the rear than the scrolling one IMHO.

Secondly use WaitBOVP(&(screen->ViewPort)) to wait for the buffer flip. I have found this works a lot better than WaitTOF().

Thirdly, when you change buffers, remember to update your W3D_Context to use the newly released buffer for rendering using W3D_SetDrawRegion(), otherwise you will be still rendering to the same BitMap that before the buffer flip was the invisible one but now is the visible one.
int p; // A
 

Offline kas1eTopic starter

Re: Warp3d synchro/double-triply bufferging
« Reply #2 on: February 11, 2005, 01:32:37 AM »
Karlos, thanks for answer.

So, i must use ScreenBuffer, and get to trash all thinks about ScrollVPort ? ok.

What about WaitBOVP(&(screen->ViewPort)) and W3D_SetDrawRegion(), as you can see in my examples, i use it already, but it is not give me good synchro.

btw, maybe you can explain more complete, what i must to do 'step-by-step' ?

I just do not understand, WHY i must use double-buffering ? Where is + ? And how i can use it ? For example:

1. i setup invisibli buffer for render:

W3D_Scissor s = {0,0,640,480};
W3D_SetDrawRegion(context,bm,480,&s),

2. draw data to this buffer.

draw_my_pict();

3. here i want to flip this buffer to main. how ?

ps. and what about YOFFSET in context creating, must i use it or not ?
 

Offline Karlos

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show only replies by Karlos
Re: Warp3d synchro/double-triply bufferging
« Reply #3 on: February 11, 2005, 02:01:53 AM »
You don't have to use the ScreenBuffer approach, I just find it works better than the tall screen / ScrollVPort method.

Right, about double (or triple) buffering in general. The basic idea is that you always draw to a BitMap that is currently invisible. Once the drawing is done, you swap this BitMap for the one currently on display (waiting for the appropriate synchronization). The BitMap you just drew on is now on screen and the one that was on screen is now available to draw on.

Doing this ensures that you never "see" the rendering happening, which would otherwise produce a very flickery image.

A consequence of this is that the "invisible" and "visible" BitMaps keep swapping over.

Therefore, regarding the W3D_SetDrawRegion() call, you have to do this every time you flip the buffers, not just when you first set up the context. From the looks of what you have written, this is the thing you are neglecting.

So every time you do the ChangeScreenBuffer(), you must also do W3D_SetDrawRegion() to tell the W3D_Context to use the "current" invisible BitMap.

One problem I noticed with your code is that you call the AllocScreenBuffer() both times using the SB_SCREEN_BITMAP argument. This arguement is used to associate the existing screen's BitMap with the ScreenBuffer, not allocate a new one. So in your case you never really had a second buffer anyway, they were both simply pointers to the screens's one. You dont use the SB_SCREEN_BITMAP when you want to actually create an invisible buffer.

Another thing to consider is that the ChangeScreenBuffer() call can fail at the point you call it. An ugly (but working) way around this is to do something like this

Screen* screen;
W3D_Scissor scissor { ... };
ScreenBuffer* buffer[2];
int drawBuffer;

//...

// create the initial visible buffer (this is just the screens bitmap)
buffer[0] = AllocScreenBuffer(screen, NULL, SB_SCREEN_BITMAP); // doesn't allcoate BitMap

// create the initial invisible buffer. Note the second argument is 0
buffer[1] = AllocScreenBuffer(screen, NULL, 0); // does allocate BitMap

// the second buffer is the initial drawing buffer
drawBuffer = 1;

// function to swap the buffers
void mySwapBuffer()
{

// make sure we swap the buffer. This truly is an ugly way, but it works - in any case, the busy loop is almost always never entered. But for the love of god don't do anything like this in a WarpOS ppc version - possible frenzy of context switches - make it a 68K function .

buffer[drawBuffer]->sb_DBufInfo->dbi_SafeMessage.mn_ReplyPort=0;
while (!ChangeScreenBuffer(screen, buffer[drawBuffer]))
  ;

// change the drawBuffer number
drawBuffer ^= 1;

// wait for bottom of viewport sync
WaitBOVP(&(screen)->ViewPort);

// update the context to use the new draw region
W3D_SetDrawRegion(context, buffer[drawBuffer]->sb_BitMap, &scissor);

}


If you use the above function (or similar - this is from memory), you should experience smooth, unflickering graphics.

Forget all about the YOffset thing, just use 0. It's only needed for the ScrollVPort() buffering strategy anyway.
int p; // A
 

Offline Karlos

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show only replies by Karlos
Re: Warp3d synchro/double-triply bufferging
« Reply #4 on: February 11, 2005, 02:43:10 AM »
Oh, a note about triple buffering...

Double buffering is your primary means of eliminating flicker by ensuring the rendering is done off screen. However, the synchronization step involved in switching the buffers can cause a stall.

Suppose you *just* miss the next monitor frame - you end up waiting for the next one after that before you can proceed to render.

Triple buffering mitigates this by using a queue of three buffers rather than a pair. This way you always have a buffer ready to render into on every monitor frame.

For systems with faster CPUs (ie capable of faster rendering), this can produce a smoother experience.
int p; // A
 

Offline kas1eTopic starter

Re: Warp3d synchro/double-triply bufferging
« Reply #5 on: February 11, 2005, 03:24:20 PM »
Do i must for ScreenBuffer techniqe use double Height screen/window ? I mean if i use 640x480 screen, can i use SA_Height/WA_Height with 480, or need 960 ? Do i need set W3D_CC_DOUBLEHEIGHT in TRUE for warp3d context ?

So, i just try to use this (with Height 480) code:

//.. open screen/window
buffer[0] = AllocScreenBuffer(screen, NULL, SB_SCREEN_BITMAP);
buffer[1] = AllocScreenBuffer(screen, NULL, 0);  drawBuffer = 1;    

// bitmap for context creating
buffer[0]->sb_DBufInfo->dbi_SafeMessage.mn_ReplyPort =NULL;
 bm = buffer[0]->sb_BitMap;  

// ..create context, set some states

for(i=250;i>0; i-=1)

{

buffer[drawBuffer]->sb_DBufInfo->dbi_SafeMessage.mn_ReplyPort=0;
while (!ChangeScreenBuffer(screen, buffer[drawBuffer]));
drawBuffer ^= 1;
WaitBOVP(&(screen)->ViewPort);
W3D_SetDrawRegion(context, buffer[drawBuffer]->sb_BitMap,0, &s);


     W3D_LockHardware(context);
     W3D_DrawTriStrip(context,&tris4); // 256x256
     W3D_DrawTriStrip(context,&tris);  // 256x256
     W3D_UnLockHardware(context);

}                      

// ..close all libs/buffers/etc
 

And i can wath as flip my buffers ! i mean for(i=250;i>0; i-=1) i can wath some time as 'flip' my buffers .. but as i understand my triangles must be not flicking, as in case if i use WaitBOVP(&(screen)->ViewPort); or WaitTOF(); only. Maybe some more initialization need it for warp3d himself, or for buffer-switching ?

First, i think maybe problem with my 040/33 (too slow), but it work the same for ppc too! i compile it for warp-os/warp3dppc and it work the same :(

ps. if you have some time, can i send to you my code/binary for test ? maybe problem in my hardware ..
 

Offline Framiga

  • Hero Member
  • *****
  • Join Date: May 2003
  • Posts: 4096
    • Show only replies by Framiga
Re: Warp3d synchro/double-triply bufferging
« Reply #6 on: February 11, 2005, 03:41:46 PM »
sorry for the intrusion but:

"Not big bugs, but some UPpers areas of my screen is 'blinking'. If i drawing in 'low' part of screen, it is work fine.. I don't know what is it, maybe problem with WaitTOF() or need do it somethink else .."

i have a similar problem with the W3DDemo "WarpTest", in the W3D archive.

CVPPC at 90 Mhz (but the same at 80) CGX42.7 with a low vertical freq>62Hz.

Thanks
 

Offline kas1eTopic starter

Re: Warp3d synchro/double-triply bufferging
« Reply #7 on: February 11, 2005, 03:58:08 PM »
to Framiga:
but what about some Demos for example ? i mean ppc/warp3d demos like mawi/encore/universe ? the same problem or work fine ?
ps. warptest work fine for me.
 

Offline Framiga

  • Hero Member
  • *****
  • Join Date: May 2003
  • Posts: 4096
    • Show only replies by Framiga
Re: Warp3d synchro/double-triply bufferging
« Reply #8 on: February 11, 2005, 04:24:01 PM »
@kas1e

just tryed again:

PaybackDemo>W3D= OK

FreespaceDemo>W3D= OK

ony WarpTest gives me those strange problem an GFX corruption on the 3D object.

EDIT- ops forgot . . .not i haven't tryed those demos (mawi/encore/universe)
 

Offline kas1eTopic starter

Re: Warp3d synchro/double-triply bufferging
« Reply #9 on: February 11, 2005, 04:28:09 PM »
@Framiga

Well, maybe normal project (like games kind of payback,etc) use other techniqe then ScrollVPort (in warptest is it), and i think not only ScreenBuffer .. Maybe 3x-buffering in here ?
 

Offline Framiga

  • Hero Member
  • *****
  • Join Date: May 2003
  • Posts: 4096
    • Show only replies by Framiga
Re: Warp3d synchro/double-triply bufferging
« Reply #10 on: February 11, 2005, 04:30:41 PM »
i'm just downloading this:

ftp://ftp.scene.org/pub/parties/2003/symphony03/amiga/demo/encore_bynight.lha

WOW fantastic :-)

works perfectly here . . . thanks

 

Offline kas1eTopic starter

Re: Warp3d synchro/double-triply bufferging
« Reply #11 on: February 11, 2005, 05:13:05 PM »
2framiga:
well, it work good with warp3d synchro too. so, i have only one question to all, how exactly it work ?:) where good example ?

ps. if you interesting in warp3d demos like ByNight from Encore, watch this:

Potion:
1. Planet Potion (work only on 15bit screens, can't work for voodoo, but it is the best)
2. Future Vision (the same).

MadWizards demos (work for me nice):

1. CruelKarma Forms (2001/the best)
2. Cull bazaar (2001).
3. another dream away (2002)
4. new dawn fades (2002)
5. heavy traffic (2002/very nice too)
6. third eye conqueror (2002/can't work on my voodoo, but it must work on CV).
7. fate fits karma (2003)
8. till i feel you (2003)

Encore:

1. Sulaco
2. ByNight
3. Kheshkhash (can't work on voodoo)

and some from CreativeMinds and Universe.

And in all GOOD SYNCHRO :)
 

Offline Karlos

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show only replies by Karlos
Re: Warp3d synchro/double-triply bufferging
« Reply #12 on: February 11, 2005, 05:50:17 PM »
@kas1e

If you want to send me your code/binary I don't mind having a quick look. I'll pmail you my email address.

I use double/triple buffered ScreenBuffers on my BPPC 68040/25 + BVision without any great problems. One of the things is knowing exactly where to put the WaitBOVP() call - it can make all the difference.

You don't need to use a ScreenBuffer for the ScrollVPort() method, it's only for the ChangeScreenBuffer() version.
int p; // A
 

Offline RWO

  • Newbie
  • *
  • Join Date: Mar 2003
  • Posts: 30
    • Show only replies by RWO
    • http://www.rwo.dk
Re: Warp3d synchro/double-triply bufferging
« Reply #13 on: February 14, 2005, 02:42:25 PM »
Karlos do you know how to do window double buffering?

-RWO
Debugging is a state of mind
 

Offline Piru

  • \' union select name,pwd--
  • Hero Member
  • *****
  • Join Date: Aug 2002
  • Posts: 6946
    • Show only replies by Piru
    • http://www.iki.fi/sintonen/
Re: Warp3d synchro/double-triply bufferging
« Reply #14 on: February 14, 2005, 04:39:00 PM »
@RWO
Quote
Karlos do you know how to do window double buffering?

There is no window buffering.