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

Reply via email to