intel: Add an interface for removing relocs after they're added.
This lets us replace the current inner drawing loop of mesa: for each prim { compute bo list if (check_aperture_space(bo list)) { batch_flush() compute bo list if (check_aperture_space(bo list)) { whine_about_batch_size() fall back; } } upload state to BOs } with this inner loop: for each prim { retry: upload state to BOs if (check_aperture_space(batch)) { if (!retried) { reset_to_last_prim() batch_flush() } else { if (batch_flush()) whine_about_batch_size() goto retry; } } } This avoids having to implement code to walk over certain sets of GL state twice (the "compute bo list" step). While it's not a performance improvement, it's a significant win in code complexity: about -200 lines, and one place to make mistakes related to aperture space instead of N places to forget some BO we should have included. Note how if we do a reset in the new loop , we immediately flush. We don't need to check aperture space -- the kernel will tell us if we actually ran out of aperture or not. And if we did run out of aperture, it's because either the single prim was too big, or because check_aperture was wrong at the point of setting up the last primitive. Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>main
parent
2c2bdb36c5
commit
515cea6ac6
|
@ -147,6 +147,8 @@ void drm_intel_bufmgr_gem_enable_reuse(drm_intel_bufmgr *bufmgr);
|
|||
void drm_intel_bufmgr_gem_enable_fenced_relocs(drm_intel_bufmgr *bufmgr);
|
||||
int drm_intel_gem_bo_map_gtt(drm_intel_bo *bo);
|
||||
int drm_intel_gem_bo_unmap_gtt(drm_intel_bo *bo);
|
||||
int drm_intel_gem_bo_get_reloc_count(drm_intel_bo *bo);
|
||||
void drm_intel_gem_bo_clear_relocs(drm_intel_bo *bo, int start);
|
||||
void drm_intel_gem_bo_start_gtt_access(drm_intel_bo *bo, int write_enable);
|
||||
|
||||
int drm_intel_get_pipe_from_crtc_id(drm_intel_bufmgr *bufmgr, int crtc_id);
|
||||
|
|
|
@ -1423,6 +1423,48 @@ drm_intel_gem_bo_emit_reloc_fence(drm_intel_bo *bo, uint32_t offset,
|
|||
read_domains, write_domain, true);
|
||||
}
|
||||
|
||||
int
|
||||
drm_intel_gem_bo_get_reloc_count(drm_intel_bo *bo)
|
||||
{
|
||||
drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
|
||||
|
||||
return bo_gem->reloc_count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes existing relocation entries in the BO after "start".
|
||||
*
|
||||
* This allows a user to avoid a two-step process for state setup with
|
||||
* counting up all the buffer objects and doing a
|
||||
* drm_intel_bufmgr_check_aperture_space() before emitting any of the
|
||||
* relocations for the state setup. Instead, save the state of the
|
||||
* batchbuffer including drm_intel_gem_get_reloc_count(), emit all the
|
||||
* state, and then check if it still fits in the aperture.
|
||||
*
|
||||
* Any further drm_intel_bufmgr_check_aperture_space() queries
|
||||
* involving this buffer in the tree are undefined after this call.
|
||||
*/
|
||||
void
|
||||
drm_intel_gem_bo_clear_relocs(drm_intel_bo *bo, int start)
|
||||
{
|
||||
drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
|
||||
int i;
|
||||
struct timespec time;
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &time);
|
||||
|
||||
assert(bo_gem->reloc_count >= start);
|
||||
/* Unreference the cleared target buffers */
|
||||
for (i = start; i < bo_gem->reloc_count; i++) {
|
||||
if (bo_gem->reloc_target_info[i].bo != bo) {
|
||||
drm_intel_gem_bo_unreference_locked_timed(bo_gem->
|
||||
reloc_target_info[i].bo,
|
||||
time.tv_sec);
|
||||
}
|
||||
}
|
||||
bo_gem->reloc_count = start;
|
||||
}
|
||||
|
||||
/**
|
||||
* Walk the tree of relocations rooted at BO and accumulate the list of
|
||||
* validations to be performed and update the relocation buffers with
|
||||
|
|
Loading…
Reference in New Issue