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 ); }