diff options
Diffstat (limited to 'src/gallium')
-rw-r--r-- | src/gallium/drivers/r300/r300_emit.c | 3 | ||||
-rw-r--r-- | src/gallium/winsys/radeon/drm/radeon_drm_cs.c | 33 | ||||
-rw-r--r-- | src/gallium/winsys/radeon/drm/radeon_drm_cs.h | 1 | ||||
-rw-r--r-- | src/gallium/winsys/radeon/drm/radeon_winsys.h | 4 |
4 files changed, 36 insertions, 5 deletions
diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c index 502aed3a20c..b953bd10f43 100644 --- a/src/gallium/drivers/r300/r300_emit.c +++ b/src/gallium/drivers/r300/r300_emit.c @@ -1238,13 +1238,12 @@ validate: r300->rws->cs_add_reloc(r300->cs, r300_resource(index_buffer)->cs_buf, r300_resource(index_buffer)->domain, 0); - /* Now do the validation. */ + /* Now do the validation (flush is called inside cs_validate on failure). */ if (!r300->rws->cs_validate(r300->cs)) { /* Ooops, an infinite loop, give up. */ if (flushed) return FALSE; - r300_flush(&r300->context, RADEON_FLUSH_ASYNC, NULL); flushed = TRUE; goto validate; } diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_cs.c b/src/gallium/winsys/radeon/drm/radeon_drm_cs.c index f0f4a70be3f..fec660d4cc8 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_cs.c +++ b/src/gallium/winsys/radeon/drm/radeon_drm_cs.c @@ -115,6 +115,7 @@ static void radeon_cs_context_cleanup(struct radeon_cs_context *csc) } csc->crelocs = 0; + csc->validated_crelocs = 0; csc->chunks[0].length_dw = 0; csc->chunks[1].length_dw = 0; csc->used_gart = 0; @@ -307,9 +308,37 @@ static void radeon_drm_cs_add_reloc(struct radeon_winsys_cs *rcs, static boolean radeon_drm_cs_validate(struct radeon_winsys_cs *rcs) { struct radeon_drm_cs *cs = radeon_drm_cs(rcs); + boolean status = + cs->csc->used_gart < cs->ws->info.gart_size * 0.8 && + cs->csc->used_vram < cs->ws->info.vram_size * 0.8; - return cs->csc->used_gart < cs->ws->info.gart_size * 0.8 && - cs->csc->used_vram < cs->ws->info.vram_size * 0.8; + if (status) { + cs->csc->validated_crelocs = cs->csc->crelocs; + } else { + /* Remove lately-added relocations. The validation failed with them + * and the CS is about to be flushed because of that. Keep only + * the already-validated relocations. */ + unsigned i; + + for (i = cs->csc->validated_crelocs; i < cs->csc->crelocs; i++) { + p_atomic_dec(&cs->csc->relocs_bo[i]->num_cs_references); + radeon_bo_reference(&cs->csc->relocs_bo[i], NULL); + } + cs->csc->crelocs = cs->csc->validated_crelocs; + + /* Flush if there are any relocs. Clean up otherwise. */ + if (cs->csc->crelocs) { + cs->flush_cs(cs->flush_data, RADEON_FLUSH_ASYNC); + } else { + radeon_cs_context_cleanup(cs->csc); + + assert(cs->base.cdw == 0); + if (cs->base.cdw != 0) { + fprintf(stderr, "radeon: Unexpected error in %s.\n", __func__); + } + } + } + return status; } static void radeon_drm_cs_write_reloc(struct radeon_winsys_cs *rcs, diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_cs.h b/src/gallium/winsys/radeon/drm/radeon_drm_cs.h index ea2a820b30a..fe285326884 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_cs.h +++ b/src/gallium/winsys/radeon/drm/radeon_drm_cs.h @@ -41,6 +41,7 @@ struct radeon_cs_context { /* Relocs. */ unsigned nrelocs; unsigned crelocs; + unsigned validated_crelocs; struct radeon_bo **relocs_bo; struct drm_radeon_cs_reloc *relocs; diff --git a/src/gallium/winsys/radeon/drm/radeon_winsys.h b/src/gallium/winsys/radeon/drm/radeon_winsys.h index f8a4d3abd43..6d52dc25022 100644 --- a/src/gallium/winsys/radeon/drm/radeon_winsys.h +++ b/src/gallium/winsys/radeon/drm/radeon_winsys.h @@ -262,7 +262,9 @@ struct radeon_winsys { /** * Return TRUE if there is enough memory in VRAM and GTT for the relocs - * added so far. + * added so far. If the validation fails, all the relocations which have + * been added since the last call of cs_validate will be removed and + * the CS will be flushed (provided there are still any relocations). * * \param cs A command stream to validate. */ |