documentation on intel driver behavior?

Dan B. Phung phung at cs.columbia.edu
Fri Feb 29 07:27:39 PST 2008


sorry, I had forgotten to cc: xorg on the reply.

Eric, thanks for the useful information.  Let me explain what I'm trying 
to do so that you understand why I'm looking in the kernel code instead 
of in just timing from the application. 

I'm trying to benchmark the frame latency of remote rendering systems 
(like chromium and aiglx).  I don't want to use the application report 
frame rate because the intermediate system could be dropping frames.  
Assuming the application doesn't use any frivolous sleeps, I start 
timing a frame right after the previous glXSwapBuffers.  I would like to 
mark the end time as the time that the frame has been completely 
rendered and displayed on the screen. 

I was previously getting this end timing by timestamping at the end of 
i915_wait_irq().  I was getting frame latencies that were too fast, so I 
tried inserting a glFinish() after the glXSwapBuffers(), and was able to 
compute latencies that were on order of what I expected.  Ideally 
though, I don't want to modify the application to insert the glFinish, 
nor do I want to assume that the glFinish is passed on to the end 
system, hence my questions about how to know in the driver that the 
frame is displayed.

So digging deep down in the code, I see that the kernel's handling of 
the swapbuffer waits in DRM_WAIT_ON().  After that's returned, then it's 
assumed that the previous frame has been swapped in....does that sound 
right? 

Another option I am considering is to force a sync either by inserting 
an MI_FLUSH at the end of the command stream, or by setting the Sync 
Enable bit and observing the Sync Status bit as described in PRM Vol 1 
sec 12.3, page 391 (see...i'm trying to rtfm :) ).  Seems like a good 
place to try either of these is in i915_dispatch_batchbuffer().

thanks for all the help thus far.


Eric Anholt wrote:
> On Wed, 2008-02-27 at 23:02 -0500, Dan B. Phung wrote:
>   
>> Eric Anholt wrote:
>>     
>>> On Wed, 2008-02-27 at 19:44 -0500, Dan B. Phung wrote:
>>>   
>>>       
>>>> Where can I find documentation on the intel drivers?  I've started to 
>>>> browse the immense hardware documentation from the 
>>>> intellinuxgraphics.org website, but trying to go from that documentation 
>>>> to reading the driver code is somewhat daunting...
>>>>     
>>>>         
>>> The documentation is the code and the comments in the code.  Some places
>>> are lacking in useful comments, but I regard that as a bug.
>>>
>>>   
>>>       
>>>> a more immediate/concrete question I have is, how does the driver know 
>>>> when a frame has finished rendering and has displayed that frame on the 
>>>> screen (e.g. when glFinish() returns)?  Is it assumed that when the 
>>>> driver returns from i915_driver_vblank_do_wait(), the frame has been 
>>>> rendered?  It's these expectations of  driver/hardware behavior that I'm 
>>>> trying to understand.
>>>>
>>>> I've tried tracing the code with printk's, but as you can 
>>>> imagine...that's somewhat tedious.  I've also loaded the module with 
>>>> 'drm debug=1' and set
>>>> #define DRM_DEBUG_CODE 2
>>>>
>>>> but...some pointers would really help...
>>>>     
>>>>         
>>> If vblank syncing is not enabled, we just flush the batchbuffer and drop
>>> a fence in copybuffers.  Before emitting another copy, we wait on an
>>> existing frame fence so that we don't get too far ahead of the hardware.
>>>   
>>>       
>> Is the fence check initiated in intelGetLastFrame()?
>>
>> In reference to the i915 driver, what's the difference between the 
>> vblank pipe A and pipe B?
>>
>>         /* Enable vblank on pipe A for older X 
>> servers                                                      
>>          */
>>         dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A;
>>
>>     
>>> For vblank syncing, we wait for vblank before emitting that copy.  Note
>>> that we're not doing anything about guaranteeing that that copy happens
>>> in any set amount of time.  We just assume that the hardware will get to
>>> it fast enough (and that we were woken up to do this soon enough) that
>>> no tearing occurs.
>>>
>>> If you wanted to know when that copy actually landed, you would glFinish
>>> after glXSwapBuffers (and glFinish would wait on the last rendering
>>> which you had done, i.e. the copy).  But glFinish isn't about frame
>>> finishing, it's about all outstanding hardware rendering.
>>>   
>>>       
>> I do actually want to know when the copy landed.   Basically, I'd like 
>> to understand the differences in how the driver/application knows when 
>> the copy has landed and how that is known in the code.  I understand at 
>> a high level that glXSwapBuffers initiates the command buffer flush and 
>> "swaps the buffers" whenever the data is "ready", but I'm interested in 
>> how you know "when the data is ready" in the code. 
>>
>>  From what I've read, glXSwapBuffers calls intelCopyBuffer, which does 
>> an intelFlush(), then intelWaitForFrameCompletion(), which eventually 
>> calls intelWaitIrq().  glFinish() also does an intelFlush() then calls 
>> intelWaitForIdle(), which also calls intelWaitIrq(). 
>>
>> intelWaitIrq() sends the ioctl:
>>  drmCommandWrite( intel->driFd, DRM_I830_IRQ_WAIT, &intel->iw, 
>> sizeof(intel->iw) );
>>
>> ...about here is where I get lost.  If both swapbuffers and finish wait 
>> for an interrupt from the hardware, how does one instance return when 
>> the data has been flushed, and the other (finish()) waits for and knows 
>> that the frame has been displayed.
>>     
>
> Huh?  Swapbuffers and finish both use the fence code.  They just wait on
> fences dropped at different times.
>
> (OK, so you're looking at the old non-TTM path.  Things weren't
> significantly different anyway, it's just cleaner now).
>
>   
>> Working under the assumption that 
>> the driver is like many other hardware drivers, I started looking from 
>> the interrupt handler i915_driver_irq_handler and I would see 
>> differences in the interrupt handling depending on whether the 
>> application calls finish() or swapbuffers().  I was expecting the 
>> finish() instance to propagate the interrupt up to the application, 
>> which the swapbuffer() instance would simply not ignore that....but I 
>> haven't seen anything like this. 
>>
>> so...what do you listen for (which region in memory do you check) to 
>> know when a copy has landed?
>>     
>
> I explained the process you would have to do if your application wanted
> to know.  And the only case the driver cares to figure out on its own is
> the wait for frame completion fence wait, which you've already seen.
>
>   



More information about the xorg mailing list