summaryrefslogtreecommitdiffstats
path: root/src/gallium
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium')
-rw-r--r--src/gallium/drivers/r300/r300_emit.c3
-rw-r--r--src/gallium/winsys/radeon/drm/radeon_drm_cs.c33
-rw-r--r--src/gallium/winsys/radeon/drm/radeon_drm_cs.h1
-rw-r--r--src/gallium/winsys/radeon/drm/radeon_winsys.h4
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.
*/