From c11ad489e7432f3ed2fcaf5b15b8fe3538ae6d30 Mon Sep 17 00:00:00 2001 From: Corbin Simpson Date: Fri, 1 May 2009 05:54:53 -0700 Subject: [PATCH] r300-gallium, radeon-winsys: Space accounting. It is no longer optional in current libdrm, so it was time to actually start counting our BOs. --- src/gallium/drivers/r300/r300_emit.c | 10 ++- src/gallium/drivers/r300/r300_surface.c | 7 ++ src/gallium/drivers/r300/r300_winsys.h | 16 +++++ .../winsys/drm/radeon/core/radeon_buffer.c | 12 +++- .../winsys/drm/radeon/core/radeon_buffer.h | 18 ++++- .../winsys/drm/radeon/core/radeon_drm.c | 4 +- .../winsys/drm/radeon/core/radeon_r300.c | 68 +++++++++++++++++++ 7 files changed, 126 insertions(+), 9 deletions(-) diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c index 74d63ffe417..01bac5f759c 100644 --- a/src/gallium/drivers/r300/r300_emit.c +++ b/src/gallium/drivers/r300/r300_emit.c @@ -424,13 +424,21 @@ void r300_emit_dirty_state(struct r300_context* r300) int i; int dirty_tex = 0; - if (!(r300->dirty_state) && !(r300->dirty_hw)) { + if (!(r300->dirty_hw)) { return; } r300_update_derived_state(r300); /* XXX check size */ + struct r300_texture* fb_tex = + (struct r300_texture*)r300->framebuffer_state.cbufs[0]; + r300->winsys->add_buffer(r300->winsys, fb_tex->buffer, + 0, RADEON_GEM_DOMAIN_VRAM); + if (r300->winsys->validate(r300->winsys)) { + /* XXX */ + r300->context.flush(&r300->context, 0, NULL); + } if (r300->dirty_state & R300_NEW_BLEND) { r300_emit_blend_state(r300, r300->blend_state); diff --git a/src/gallium/drivers/r300/r300_surface.c b/src/gallium/drivers/r300/r300_surface.c index 79bed032538..4dd5b8af99a 100644 --- a/src/gallium/drivers/r300/r300_surface.c +++ b/src/gallium/drivers/r300/r300_surface.c @@ -34,6 +34,13 @@ static void r300_surface_setup(struct pipe_context* pipe, unsigned pixpitch = tex->stride / tex->tex.block.size; CS_LOCALS(r300); + /* Make sure our target BO is okay. */ + r300->winsys->add_buffer(r300->winsys, tex->buffer, + 0, RADEON_GEM_DOMAIN_VRAM); + if (r300->winsys->validate(r300->winsys)) { + r300->context.flush(&r300->context, 0, NULL); + } + r300_emit_blend_state(r300, &blend_clear_state); r300_emit_blend_color_state(r300, &blend_color_clear_state); r300_emit_dsa_state(r300, &dsa_clear_state); diff --git a/src/gallium/drivers/r300/r300_winsys.h b/src/gallium/drivers/r300/r300_winsys.h index 393ba07012b..761aedebfcf 100644 --- a/src/gallium/drivers/r300/r300_winsys.h +++ b/src/gallium/drivers/r300/r300_winsys.h @@ -53,6 +53,22 @@ struct r300_winsys { /* GB pipe count */ uint32_t gb_pipes; + /* GART size. */ + uint32_t gart_size; + + /* VRAM size. */ + uint32_t vram_size; + + /* Add a pipe_buffer to the list of buffer objects to validate. */ + void (*add_buffer)(struct r300_winsys* winsys, + struct pipe_buffer* pbuffer, + uint32_t rd, + uint32_t wd); + + /* Revalidate all currently setup pipe_buffers. + * Returns TRUE if a flush is required. */ + boolean (*validate)(struct r300_winsys* winsys); + /* Check to see if there's room for commands. */ boolean (*check_cs)(struct r300_winsys* winsys, int size); diff --git a/src/gallium/winsys/drm/radeon/core/radeon_buffer.c b/src/gallium/winsys/drm/radeon/core/radeon_buffer.c index 611ee68da63..6313eb219ec 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_buffer.c +++ b/src/gallium/winsys/drm/radeon/core/radeon_buffer.c @@ -68,8 +68,8 @@ static struct pipe_buffer *radeon_buffer_create(struct pipe_winsys *ws, domain |= RADEON_GEM_DOMAIN_GTT; } - radeon_buffer->bo = radeon_bo_open(radeon_ws->bom, 0, size, alignment, - domain, 0); + radeon_buffer->bo = radeon_bo_open(radeon_ws->priv->bom, 0, size, + alignment, domain, 0); if (radeon_buffer->bo == NULL) { FREE(radeon_buffer); } @@ -169,8 +169,14 @@ struct radeon_winsys* radeon_pipe_winsys(int fd) return NULL; } + radeon_ws->priv = CALLOC_STRUCT(radeon_winsys_priv); + if (radeon_ws->priv == NULL) { + FREE(radeon_ws); + return NULL; + } + bom = radeon_bo_manager_gem_ctor(fd); - radeon_ws->bom = bom; + radeon_ws->priv->bom = bom; radeon_ws->base.flush_frontbuffer = radeon_flush_frontbuffer; diff --git a/src/gallium/winsys/drm/radeon/core/radeon_buffer.h b/src/gallium/winsys/drm/radeon/core/radeon_buffer.h index 163422f2969..73fa362acab 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_buffer.h +++ b/src/gallium/winsys/drm/radeon/core/radeon_buffer.h @@ -41,6 +41,7 @@ #include "util/u_memory.h" #include "radeon_bo.h" +#include "radeon_cs.h" #include "radeon_drm.h" @@ -49,13 +50,24 @@ struct radeon_pipe_buffer { struct radeon_bo *bo; }; +#define RADEON_MAX_BOS 24 + +struct radeon_winsys_priv { + /* Radeon BO manager. */ + struct radeon_bo_manager* bom; + + /* Radeon BO space checker. */ + struct radeon_cs_space_check sc[RADEON_MAX_BOS]; + /* Current BO count. */ + unsigned bo_count; +}; + struct radeon_winsys { /* Parent class. */ struct pipe_winsys base; - /* Radeon BO manager. - * This corresponds to void* radeon_winsys in r300_winsys. */ - struct radeon_bo_manager* bom; + /* This corresponds to void* radeon_winsys in r300_winsys. */ + struct radeon_winsys_priv* priv; }; struct radeon_winsys* radeon_pipe_winsys(int fb); diff --git a/src/gallium/winsys/drm/radeon/core/radeon_drm.c b/src/gallium/winsys/drm/radeon/core/radeon_drm.c index 1f89d1b1d10..428d3f65a16 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_drm.c +++ b/src/gallium/winsys/drm/radeon/core/radeon_drm.c @@ -32,7 +32,7 @@ /* Create a pipe_screen. */ struct pipe_screen* radeon_create_screen(int drmFB, - struct drm_create_screen_arg *arg ) + struct drm_create_screen_arg *arg) { struct radeon_winsys* winsys = radeon_pipe_winsys(drmFB); @@ -69,7 +69,7 @@ struct pipe_buffer* radeon_buffer_from_handle(struct pipe_screen* screen, unsigned handle) { struct radeon_bo_manager* bom = - ((struct radeon_winsys*)screen->winsys)->bom; + ((struct radeon_winsys*)screen->winsys)->priv->bom; struct radeon_pipe_buffer* radeon_buffer; struct radeon_bo* bo = NULL; diff --git a/src/gallium/winsys/drm/radeon/core/radeon_r300.c b/src/gallium/winsys/drm/radeon/core/radeon_r300.c index 929e4842ccf..b1721074322 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_r300.c +++ b/src/gallium/winsys/drm/radeon/core/radeon_r300.c @@ -22,6 +22,54 @@ #include "radeon_r300.h" +static void radeon_r300_add_buffer(struct r300_winsys* winsys, + struct pipe_buffer* pbuffer, + uint32_t rd, + uint32_t wd) +{ + int i; + struct radeon_winsys_priv* priv = + (struct radeon_winsys_priv*)winsys->radeon_winsys; + struct radeon_cs_space_check* sc = priv->sc; + struct radeon_bo* bo = ((struct radeon_pipe_buffer*)pbuffer)->bo; + + /* Check to see if this BO is already in line for validation; + * find a slot for it otherwise. */ + for (i = 0; i < RADEON_MAX_BOS; i++) { + if (sc[i].bo == bo) { + return; + } else if (sc[i].bo == NULL) { + sc[i].bo = bo; + sc[i].read_domains = rd; + sc[i].write_domain = wd; + priv->bo_count = i + 1; + return; + } + } + + assert(FALSE && "Oh God too many BOs!"); +} + +static boolean radeon_r300_validate(struct r300_winsys* winsys) +{ + int retval; + struct radeon_winsys_priv* priv = + (struct radeon_winsys_priv*)winsys->radeon_winsys; + struct radeon_cs_space_check* sc = priv->sc; + + retval = radeon_cs_space_check(winsys->cs, sc, priv->bo_count); + + if (retval == RADEON_CS_SPACE_OP_TO_BIG) { + /* XXX we need to failover here */ + } else if (retval == RADEON_CS_SPACE_FLUSH) { + /* We must flush before more rendering can commence. */ + return TRUE; + } + + /* Things are fine, we can proceed as normal. */ + return FALSE; +} + static boolean radeon_r300_check_cs(struct r300_winsys* winsys, int size) { /* XXX check size here, lazy ass! */ @@ -77,6 +125,7 @@ static void radeon_r300_flush_cs(struct r300_winsys* winsys) /* Helper function to do the ioctls needed for setup and init. */ static void do_ioctls(struct r300_winsys* winsys, int fd) { + struct drm_radeon_gem_info info; drm_radeon_getparam_t gp; int target; int retval; @@ -102,6 +151,18 @@ static void do_ioctls(struct r300_winsys* winsys, int fd) exit(1); } winsys->pci_id = target; + + /* Finally, retrieve MM info */ + retval = drmCommandWriteRead(fd, DRM_RADEON_GEM_INFO, + &info, sizeof(info)); + if (retval) { + fprintf(stderr, "%s: Failed to get MM info, error number %d\n", + __FUNCTION__, retval); + exit(1); + } + winsys->gart_size = info.gart_size; + /* XXX */ + winsys->vram_size = info.vram_visible; } struct r300_winsys* @@ -119,6 +180,13 @@ radeon_create_r300_winsys(int fd, struct radeon_winsys* old_winsys) csm = radeon_cs_manager_gem_ctor(fd); winsys->cs = radeon_cs_create(csm, 1024 * 64 / 4); + radeon_cs_set_limit(winsys->cs, + RADEON_GEM_DOMAIN_GTT, winsys->gart_size); + radeon_cs_set_limit(winsys->cs, + RADEON_GEM_DOMAIN_VRAM, winsys->vram_size); + + winsys->add_buffer = radeon_r300_add_buffer; + winsys->validate = radeon_r300_validate; winsys->check_cs = radeon_r300_check_cs; winsys->begin_cs = radeon_r300_begin_cs; -- 2.30.2