r300-gallium, radeon-winsys: Space accounting.
authorCorbin Simpson <MostAwesomeDude@gmail.com>
Fri, 1 May 2009 12:54:53 +0000 (05:54 -0700)
committerCorbin Simpson <MostAwesomeDude@gmail.com>
Fri, 1 May 2009 12:54:53 +0000 (05:54 -0700)
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
src/gallium/drivers/r300/r300_surface.c
src/gallium/drivers/r300/r300_winsys.h
src/gallium/winsys/drm/radeon/core/radeon_buffer.c
src/gallium/winsys/drm/radeon/core/radeon_buffer.h
src/gallium/winsys/drm/radeon/core/radeon_drm.c
src/gallium/winsys/drm/radeon/core/radeon_r300.c

index 74d63ffe417bf88d088b5ab3d8148d8cd72d31b3..01bac5f759cb1c635cf02a5308ff5766b635bca8 100644 (file)
@@ -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);
index 79bed0325388a9abff52e99900259c1e1ee7a8ec..4dd5b8af99a5e052f4a5991164ad4b347305947f 100644 (file)
@@ -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);
index 393ba07012b5a427dce1a7a5b36b538ef2daa738..761aedebfcfb1871dea0a5ecd21ba301c2d71392 100644 (file)
@@ -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);
 
index 611ee68da63e0c3e5ea196c9b2c89ce85aa18436..6313eb219eca7a0a4381b430e36ed678b38261b7 100644 (file)
@@ -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;
 
index 163422f29692966401a250f02db9f1e50e97da6b..73fa362acab3aacb834d02cec40fc9ca34c7b42d 100644 (file)
@@ -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);
index 1f89d1b1d10f170cf4a1ad511c59f4c089faf857..428d3f65a169be009d8e00395b84e162bec203f1 100644 (file)
@@ -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;
 
index 929e4842ccfafe75c24e79645359b024ff8968ab..b17210743220f0d1ebfcc06b335f94187ff357ed 100644 (file)
 
 #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;