On Sat, 28 Sep 2002 14:56:38 +0100
Keith Whitwell <[EMAIL PROTECTED]> wrote:
> Felix K�hling wrote:
> > Hi,
> >
> > I was able to reduce CPU usage of applications which use glFinish by
> > emitting and waiting for an IRQ in radeonFinish before
> > radeonWaitForIdle. I'm not sure whether radeonWaitForIdle is still
> > needed after waiting for the IRQ, but keeping it does at least not hurt.
> > The patch is attached.
> >
> > One more thing: Since radeonWaitForFrameCompletion uses IRQs there are
> > no more lag problems. Because the IRQ emit is the last thing on the ring
> > all frames are finished when the IRQ is received. So checking for
> > MAX_OUTSTANDING in a loop is no longer necessary in that case, right?
> >
> > Best regards,
> > Felix
>
> Felix, I'd prefer to leave that code as it is for now. Specifically, I'd
> like to see a situation where the irq's are used to allow at most 1 frame
> outstanding, whereas they currently allow zero, which I believe is suboptimal.
Ok, what do you think about this one? It waits for the IRQ emitted in
the previous call to WaitForFrameCompletion and emits a new one to be
waited for the next time. It relies on the implementation of
radeon_wait_irq which returns immediately if the irq you're waiting for
has allready occured. So I don't have to worry about checking if I
missed the IRQ.
I tested it with and without page flipping. Q3 and Torcs looked a bit
jerky before, but now they run perfectly smooth.
> The code is a simple test of irqs & should either stay as it is, or get fixed
> properly.
>
> I like the patch below, however. There's no need for the WaitForIdle any
> more, I think.
>
> Keith
__\|/__ ___ ___ ___
__Tsch��_______\_6 6_/___/__ \___/__ \___/___\___You can do anything,___
_____Felix_______\�/\ \_____\ \_____\ \______U___just not everything____
[EMAIL PROTECTED] >o<__/ \___/ \___/ at the same time!
Index: radeon_ioctl.c
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/radeon/radeon_ioctl.c,v
retrieving revision 1.24
diff -u -r1.24 radeon_ioctl.c
--- radeon_ioctl.c 25 Sep 2002 17:20:30 -0000 1.24
+++ radeon_ioctl.c 28 Sep 2002 14:54:19 -0000
@@ -623,63 +623,69 @@
static int radeonWaitForFrameCompletion( radeonContextPtr rmesa )
{
- unsigned char *RADEONMMIO = rmesa->radeonScreen->mmio.map;
RADEONSAREAPrivPtr sarea = rmesa->sarea;
- CARD32 frame;
- int wait = 0;
int fd = rmesa->dri.fd;
+ int wait = 0;
- while ( 1 ) {
+ if (rmesa->do_irqs) {
int ret;
- if (rmesa->dri.screen->drmMinor >= 4) {
- drmRadeonGetParam gp;
-
- gp.param = RADEON_PARAM_LAST_FRAME;
- gp.value = (int *)&frame;
- ret = drmCommandWriteRead( fd, DRM_RADEON_GETPARAM, &gp, sizeof(gp) );
- } else
- ret = -EINVAL;
-
- if ( ret == -EINVAL ) {
- frame = INREG( RADEON_LAST_FRAME_REG );
- } else if ( ret ) {
- fprintf( stderr, "%s: drmRadeonGetParam: %d\n", __FUNCTION__, ret );
- exit(1);
- }
- if ( RADEON_DEBUG & DEBUG_IOCTL ) {
- fprintf( stderr, "%s( %d )\n", __FUNCTION__, (int)frame );
- if ( ret ) fprintf( stderr, " ( RADEON_LAST_FRAME register read directly )\n"
);
- }
+ static drmRadeonIrqWait iw = {-1};
+ drmRadeonIrqEmit ie;
- if ( sarea->last_frame - frame <= RADEON_MAX_OUTSTANDING ) {
- break;
+ /* if there was a previous frame, wait for its IRQ */
+ if (iw.irq_seq != -1) {
+ UNLOCK_HARDWARE( rmesa );
+ ret = drmCommandWrite( fd, DRM_RADEON_IRQ_WAIT, &iw, sizeof(iw) );
+ if ( ret ) {
+ fprintf( stderr, "%s: drmRadeonIrqWait: %d\n", __FUNCTION__, ret );
+ exit(1);
+ }
+ LOCK_HARDWARE( rmesa );
+ }
+
+ /* emit an IRQ for this frame, will be waited for after the next frame */
+ ie.irq_seq = &iw.irq_seq;
+ ret = drmCommandWriteRead( fd, DRM_RADEON_IRQ_EMIT, &ie, sizeof(ie) );
+ if ( ret ) {
+ fprintf( stderr, "%s: drmRadeonIrqEmit: %d\n", __FUNCTION__, ret );
+ exit(1);
}
- wait++;
+ } else {
+ unsigned char *RADEONMMIO = rmesa->radeonScreen->mmio.map;
+ CARD32 frame;
- if (rmesa->do_irqs) {
- drmRadeonIrqEmit ie;
- drmRadeonIrqWait iw;
+ while ( 1 ) {
+ int ret;
- ie.irq_seq = &iw.irq_seq;
+ if (rmesa->dri.screen->drmMinor >= 4) {
+ drmRadeonGetParam gp;
- ret = drmCommandWriteRead( fd, DRM_RADEON_IRQ_EMIT, &ie, sizeof(ie) );
- if ( ret ) {
- fprintf( stderr, "%s: drmRadeonIrqEmit: %d\n", __FUNCTION__, ret );
- exit(1);
- }
-
- UNLOCK_HARDWARE( rmesa );
- ret = drmCommandWrite( fd, DRM_RADEON_IRQ_WAIT, &iw, sizeof(iw) );
- if ( ret ) {
- fprintf( stderr, "%s: drmRadeonIrqWait: %d\n", __FUNCTION__, ret );
- exit(1);
- }
- LOCK_HARDWARE( rmesa );
- } else if (rmesa->do_usleeps) {
- UNLOCK_HARDWARE( rmesa );
- do_usleep(1, __FUNCTION__);
- LOCK_HARDWARE( rmesa );
+ gp.param = RADEON_PARAM_LAST_FRAME;
+ gp.value = (int *)&frame;
+ ret = drmCommandWriteRead( fd, DRM_RADEON_GETPARAM, &gp, sizeof(gp) );
+ } else
+ ret = -EINVAL;
+
+ if ( ret == -EINVAL ) {
+ frame = INREG( RADEON_LAST_FRAME_REG );
+ } else if ( ret ) {
+ fprintf( stderr, "%s: drmRadeonGetParam: %d\n", __FUNCTION__, ret );
+ exit(1);
+ }
+ if ( RADEON_DEBUG & DEBUG_IOCTL ) {
+ fprintf( stderr, "%s( %d )\n", __FUNCTION__, (int)frame );
+ if ( ret ) fprintf( stderr, " ( RADEON_LAST_FRAME register read directly
+)\n" );
+ }
+
+ if ( sarea->last_frame - frame <= RADEON_MAX_OUTSTANDING ) {
+ break;
+ }
+ wait++;
+
+ UNLOCK_HARDWARE( rmesa );
+ do_usleep(1, __FUNCTION__);
+ LOCK_HARDWARE( rmesa );
}
}
@@ -1090,6 +1096,29 @@
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
radeonFlush( ctx );
+ if (rmesa->do_irqs) {
+ int fd = rmesa->dri.fd;
+ int ret;
+
+ drmRadeonIrqEmit ie;
+ drmRadeonIrqWait iw;
+
+ ie.irq_seq = &iw.irq_seq;
+
+ LOCK_HARDWARE( rmesa );
+ ret = drmCommandWriteRead( fd, DRM_RADEON_IRQ_EMIT, &ie, sizeof(ie) );
+ if ( ret ) {
+ fprintf( stderr, "%s: drmRadeonIrqEmit: %d\n", __FUNCTION__, ret );
+ exit(1);
+ }
+ UNLOCK_HARDWARE( rmesa );
+
+ ret = drmCommandWrite( fd, DRM_RADEON_IRQ_WAIT, &iw, sizeof(iw) );
+ if ( ret ) {
+ fprintf( stderr, "%s: drmRadeonIrqWait: %d\n", __FUNCTION__, ret );
+ exit(1);
+ }
+ }
radeonWaitForIdle( rmesa );
}