summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2009-01-31 01:50:23 +1000
committerThomas Hellstrom <thomas-at-shipmail-dot-org>2009-02-03 22:22:43 +0100
commitaa5612d308405b1c9af1fd3fcdb32f1ff1b905c0 (patch)
tree12e2e3ba59cd8d53a0b1d25ac135bed59c685042
parent2e3f86c2a07ac2329fe1ddaff62af5285c13f2f6 (diff)
radeon: add space accounting to cs code
-rw-r--r--libdrm/radeon/radeon_bo.h1
-rw-r--r--libdrm/radeon/radeon_cs.h35
-rw-r--r--libdrm/radeon/radeon_cs_gem.c105
3 files changed, 140 insertions, 1 deletions
diff --git a/libdrm/radeon/radeon_bo.h b/libdrm/radeon/radeon_bo.h
index 9de4fcc2..3cabdfc4 100644
--- a/libdrm/radeon/radeon_bo.h
+++ b/libdrm/radeon/radeon_bo.h
@@ -52,6 +52,7 @@ struct radeon_bo {
#endif
void *ptr;
struct radeon_bo_manager *bom;
+ uint32_t space_accounted;
};
/* bo functions */
diff --git a/libdrm/radeon/radeon_cs.h b/libdrm/radeon/radeon_cs.h
index 8b1a9993..8b5a2a92 100644
--- a/libdrm/radeon/radeon_cs.h
+++ b/libdrm/radeon/radeon_cs.h
@@ -33,6 +33,8 @@
#define RADEON_CS_H
#include <stdint.h>
+#include "drm.h"
+#include "radeon_drm.h"
#include "radeon_bo.h"
struct radeon_cs_reloc {
@@ -42,6 +44,18 @@ struct radeon_cs_reloc {
uint32_t flags;
};
+
+#define RADEON_CS_SPACE_OK 0
+#define RADEON_CS_SPACE_OP_TO_BIG 1
+#define RADEON_CS_SPACE_FLUSH 2
+
+struct radeon_cs_space_check {
+ struct radeon_bo *bo;
+ uint32_t read_domains;
+ uint32_t write_domain;
+ uint32_t new_accounted;
+};
+
struct radeon_cs_manager;
struct radeon_cs {
@@ -58,6 +72,7 @@ struct radeon_cs {
const char *section_file;
const char *section_func;
int section_line;
+
};
/* cs functions */
@@ -84,11 +99,16 @@ struct radeon_cs_funcs {
int (*cs_erase)(struct radeon_cs *cs);
int (*cs_need_flush)(struct radeon_cs *cs);
void (*cs_print)(struct radeon_cs *cs, FILE *file);
+ int (*cs_space_check)(struct radeon_cs *cs, struct radeon_cs_space_check *bos,
+ int num_bo);
};
struct radeon_cs_manager {
struct radeon_cs_funcs *funcs;
int fd;
+ uint32_t vram_limit, gart_limit;
+ uint32_t vram_write_used, gart_write_used;
+ uint32_t read_used;
};
static inline struct radeon_cs *radeon_cs_create(struct radeon_cs_manager *csm,
@@ -157,4 +177,19 @@ static inline void radeon_cs_print(struct radeon_cs *cs, FILE *file)
cs->csm->funcs->cs_print(cs, file);
}
+static inline int radeon_cs_space_check(struct radeon_cs *cs,
+ struct radeon_cs_space_check *bos,
+ int num_bo)
+{
+ return cs->csm->funcs->cs_space_check(cs, bos, num_bo);
+}
+
+static inline void radeon_cs_set_limit(struct radeon_cs *cs, uint32_t domain, uint32_t limit)
+{
+
+ if (domain == RADEON_GEM_DOMAIN_VRAM)
+ cs->csm->vram_limit = limit;
+ else
+ cs->csm->gart_limit = limit;
+}
#endif
diff --git a/libdrm/radeon/radeon_cs_gem.c b/libdrm/radeon/radeon_cs_gem.c
index bfc5aca6..c9cf345b 100644
--- a/libdrm/radeon/radeon_cs_gem.c
+++ b/libdrm/radeon/radeon_cs_gem.c
@@ -229,6 +229,16 @@ static int cs_gem_end(struct radeon_cs *cs,
return 0;
}
+
+static void dump_cmdbuf(struct radeon_cs *cs)
+{
+ int i;
+ for (i = 0; i < cs->cdw; i++){
+ fprintf(stderr,"%x: %08x\n", i, cs->packets[i]);
+ }
+
+}
+
static int cs_gem_emit(struct radeon_cs *cs)
{
struct cs_gem *csg = (struct cs_gem*)cs;
@@ -236,6 +246,7 @@ static int cs_gem_emit(struct radeon_cs *cs)
unsigned i;
int r;
+ dump_cmdbuf(cs);
csg->chunks[0].length_dw = cs->cdw;
chunk_array[0] = (uint64_t)(intptr_t)&csg->chunks[0];
@@ -387,6 +398,97 @@ static void cs_gem_print(struct radeon_cs *cs, FILE *file)
}
}
+static int cs_gem_check_space(struct radeon_cs *cs, struct radeon_cs_space_check *bos, int num_bo)
+{
+ struct radeon_cs_manager *csm = cs->csm;
+ int this_op_read = 0, this_op_gart_write = 0, this_op_vram_write = 0;
+ uint32_t read_domains, write_domain;
+ int i;
+ struct radeon_bo *bo;
+
+ /* check the totals for this operation */
+
+ if (num_bo == 0)
+ return 0;
+
+ /* prepare */
+ for (i = 0; i < num_bo; i++) {
+ bo = bos[i].bo;
+
+ bos[i].new_accounted = 0;
+ read_domains = bos[i].read_domains;
+ write_domain = bos[i].write_domain;
+
+ /* already accounted this bo */
+ if (write_domain && (write_domain == bo->space_accounted))
+ continue;
+
+ if (read_domains && ((read_domains << 16) == bo->space_accounted))
+ continue;
+
+ if (bo->space_accounted == 0) {
+ if (write_domain == RADEON_GEM_DOMAIN_VRAM)
+ this_op_vram_write += bo->size;
+ else if (write_domain == RADEON_GEM_DOMAIN_GTT)
+ this_op_gart_write += bo->size;
+ else
+ this_op_read += bo->size;
+ bos[i].new_accounted = (read_domains << 16) | write_domain;
+ } else {
+ uint16_t old_read, old_write;
+
+ old_read = bo->space_accounted >> 16;
+ old_write = bo->space_accounted & 0xffff;
+
+ if (write_domain && (old_read & write_domain)) {
+ bos[i].new_accounted = write_domain;
+ /* moving from read to a write domain */
+ if (write_domain == RADEON_GEM_DOMAIN_VRAM) {
+ this_op_read -= bo->size;
+ this_op_vram_write += bo->size;
+ } else if (write_domain == RADEON_GEM_DOMAIN_VRAM) {
+ this_op_read -= bo->size;
+ this_op_gart_write += bo->size;
+ }
+ } else if (read_domains & old_write) {
+ bos[i].new_accounted = bo->space_accounted & 0xffff;
+ } else {
+ /* rewrite the domains */
+ if (write_domain != old_write)
+ fprintf(stderr,"WRITE DOMAIN RELOC FAILURE 0x%x %d %d\n", bo->handle, write_domain, old_write);
+ if (read_domains != old_read)
+ fprintf(stderr,"READ DOMAIN RELOC FAILURE 0x%x %d %d\n", bo->handle, read_domains, old_read);
+ return RADEON_CS_SPACE_FLUSH;
+ }
+ }
+ }
+
+ if (this_op_read < 0)
+ this_op_read = 0;
+
+ /* check sizes - operation first */
+ if ((this_op_read + this_op_gart_write > csm->gart_limit) ||
+ (this_op_vram_write > csm->vram_limit)) {
+ return RADEON_CS_SPACE_OP_TO_BIG;
+ }
+
+ if (((csm->vram_write_used + this_op_vram_write) > csm->vram_limit) ||
+ ((csm->read_used + csm->gart_write_used + this_op_gart_write + this_op_read) > csm->gart_limit)) {
+ return RADEON_CS_SPACE_FLUSH;
+ }
+
+ csm->gart_write_used += this_op_gart_write;
+ csm->vram_write_used += this_op_vram_write;
+ csm->read_used += this_op_read;
+ /* commit */
+ for (i = 0; i < num_bo; i++) {
+ bo = bos[i].bo;
+ bo->space_accounted = bos[i].new_accounted;
+ }
+
+ return RADEON_CS_SPACE_OK;
+}
+
static struct radeon_cs_funcs radeon_cs_gem_funcs = {
cs_gem_create,
cs_gem_write_dword,
@@ -397,7 +499,8 @@ static struct radeon_cs_funcs radeon_cs_gem_funcs = {
cs_gem_destroy,
cs_gem_erase,
cs_gem_need_flush,
- cs_gem_print
+ cs_gem_print,
+ cs_gem_check_space,
};
struct radeon_cs_manager *radeon_cs_manager_gem_ctor(int fd)