diff --git a/libdrm/radeon/radeon_bo.h b/libdrm/radeon/radeon_bo.h index 44dc090..3cabdfc 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 */ @@ -66,6 +67,7 @@ struct radeon_bo_funcs { struct radeon_bo *(*bo_unref)(struct radeon_bo *bo); int (*bo_map)(struct radeon_bo *bo, int write); int (*bo_unmap)(struct radeon_bo *bo); + int (*bo_wait)(struct radeon_bo *bo); }; struct radeon_bo_manager { @@ -151,6 +153,14 @@ static inline int _radeon_bo_unmap(struct radeon_bo *bo, return bo->bom->funcs->bo_unmap(bo); } +static inline int _radeon_bo_wait(struct radeon_bo *bo, + const char *file, + const char *func, + int line) +{ + return bo->bom->funcs->bo_wait(bo); +} + #define radeon_bo_open(bom, h, s, a, d, f)\ _radeon_bo_open(bom, h, s, a, d, f, __FILE__, __FUNCTION__, __LINE__) #define radeon_bo_ref(bo)\ @@ -163,5 +173,7 @@ static inline int _radeon_bo_unmap(struct radeon_bo *bo, _radeon_bo_unmap(bo, __FILE__, __FUNCTION__, __LINE__) #define radeon_bo_debug(bo, opcode)\ _radeon_bo_debug(bo, opcode, __FILE__, __FUNCTION__, __LINE__) +#define radeon_bo_wait(bo) \ + _radeon_bo_wait(bo, __FILE__, __func__, __LINE__) #endif diff --git a/libdrm/radeon/radeon_bo_gem.c b/libdrm/radeon/radeon_bo_gem.c index fdf852a..932afeb 100644 --- a/libdrm/radeon/radeon_bo_gem.c +++ b/libdrm/radeon/radeon_bo_gem.c @@ -35,6 +35,7 @@ #include #include #include +#include #include "xf86drm.h" #include "drm.h" #include "radeon_drm.h" @@ -176,12 +177,26 @@ static int bo_unmap(struct radeon_bo *bo) return 0; } +static int bo_wait(struct radeon_bo *bo) +{ + struct drm_radeon_gem_wait_rendering args; + int ret; + + args.handle = bo->handle; + do { + ret = drmCommandWriteRead(bo->bom->fd, DRM_RADEON_GEM_WAIT_RENDERING, + &args, sizeof(args)); + } while (ret == -EAGAIN); + return ret; +} + static struct radeon_bo_funcs bo_gem_funcs = { bo_open, bo_ref, bo_unref, bo_map, - bo_unmap + bo_unmap, + bo_wait }; struct radeon_bo_manager *radeon_bo_manager_gem_ctor(int fd) diff --git a/libdrm/radeon/radeon_cs.h b/libdrm/radeon/radeon_cs.h index 8b1a999..8b5a2a9 100644 --- a/libdrm/radeon/radeon_cs.h +++ b/libdrm/radeon/radeon_cs.h @@ -33,6 +33,8 @@ #define RADEON_CS_H #include +#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 bfc5aca..c9cf345 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) diff --git a/shared-core/radeon_drm.h b/shared-core/radeon_drm.h index fd26eee..b989649 100644 --- a/shared-core/radeon_drm.h +++ b/shared-core/radeon_drm.h @@ -711,6 +711,7 @@ typedef struct drm_radeon_indirect { #define RADEON_PARAM_FB_LOCATION 14 /* FB location */ #define RADEON_PARAM_NUM_GB_PIPES 15 /* num GB pipes */ #define RADEON_PARAM_KERNEL_MM 16 +#define RADEON_PARAM_DEVICE_ID 17 typedef struct drm_radeon_getparam { int param;