Skip to content
  • Kenneth Graunke's avatar
    i965: Use a separate state buffer, but avoid changing flushing behavior. · 78c404f1
    Kenneth Graunke authored
    
    
    Previously, we emitted GPU commands and indirect state into the same
    buffer, using a stack/heap like system where we filled in commands from
    the start of the buffer, and state from the end of the buffer.  We then
    flushed before the two met in the middle.
    
    Meeting in the middle is fatal, so you have to be certain that you
    reserve the correct amount of space before emitting commands or state
    for a draw.  Currently, we will assert !no_batch_wrap and die if the
    estimate is ever too small.  This has been mercifully obscure, but has
    happened on a number of occasions, and could in theory happen to any
    application that issues a large draw at just the wrong time.
    
    Estimating the amount of batch space required is painful - it's hard to
    get right, and getting it right involves a lot of code that would burn
    CPU time, and also be painful to maintain.  Rolling back to a saved
    state and retrying is also painful - failing to save/restore all the
    required state will break things, and redoing state emission burns a
    lot of CPU.  memcpy'ing to a new batch and continuing is painful,
    because commands we issue for a draw depend on earlier commands as well
    (such as STATE_BASE_ADDRESS, or the GPU being in a pirtacular state).
    
    The best plan is to never run out of space, which is totally doable but
    pretty wasteful - a pessimal draw requires a huge amount of space, and
    rarely occurs.  Instead, we'd like to grow the batch buffer if we need
    more space and can't safely flush.
    
    We can't grow with a meet in the middle approach - we'd have to move the
    state to the end, which would mean updating every offset from dynamic
    state base address.  Using separate batch and state buffers, where both
    fill starting at the beginning, makes it easy to grow either as needed.
    
    This patch separates the two concepts.  We create a separate state
    buffer, with a second relocation list, and use that for brw_state_batch.
    
    However, this patch tries to retain the original flushing behavior - it
    adds the amount of batch and state space together, as if they were still
    co-existing in a single buffer.  The hope is to flush at the same time
    as before.  This is necessary to avoid provoking bugs caused by broken
    batch wrap handling (which we'll fix shortly).  It also avoids suddenly
    increasing the size of the batch (due to state not taking up space),
    which could have a significant performance impact.  We'll tune it later.
    
    v2:
    - Mark the statebuffer with EXEC_OBJECT_CAPTURE when supported (caught
      by Chris).  Unfortunately, we lose the ability to capture state data
      on older kernels.
    - Continue to support the malloc'd shadow buffers.
    
    Reviewed-by: default avatarMatt Turner <mattst88@gmail.com>
    Reviewed-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
    78c404f1