diff options
author | Dave Airlie <airlied@redhat.com> | 2009-01-31 01:50:23 +1000 |
---|---|---|
committer | Thomas Hellstrom <thomas-at-shipmail-dot-org> | 2009-02-03 22:22:43 +0100 |
commit | aa5612d308405b1c9af1fd3fcdb32f1ff1b905c0 (patch) | |
tree | 12e2e3ba59cd8d53a0b1d25ac135bed59c685042 | |
parent | 2e3f86c2a07ac2329fe1ddaff62af5285c13f2f6 (diff) |
radeon: add space accounting to cs code
-rw-r--r-- | libdrm/radeon/radeon_bo.h | 1 | ||||
-rw-r--r-- | libdrm/radeon/radeon_cs.h | 35 | ||||
-rw-r--r-- | libdrm/radeon/radeon_cs_gem.c | 105 |
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) |