r600g: reduce memory usage from range/block hash table.
authorDave Airlie <airlied@redhat.com>
Thu, 12 May 2011 03:20:02 +0000 (13:20 +1000)
committerDave Airlie <airlied@redhat.com>
Thu, 12 May 2011 23:22:40 +0000 (09:22 +1000)
This table covered a large range unnecessarily, reduce the address
range covered, use the fact that the bottom two bits aren't significant,
and remove unused fields from the range struct. It also drops the hash_size/shift in context in favour of a define, which should make doing the math
a bit less CPU intensive.

valgrind glxinfo
Before:
==320==     in use at exit: 419,754 bytes in 706 blocks
==320==   total heap usage: 3,691 allocs, 2,985 frees, 7,272,467 bytes allocated

After:
==967==     in use at exit: 419,754 bytes in 706 blocks
==967==   total heap usage: 3,552 allocs, 2,846 frees, 3,550,131 bytes allocated

Signed-off-by: Dave Airlie <airlied@redhat.com>
src/gallium/drivers/r600/r600.h
src/gallium/winsys/r600/drm/evergreen_hw_context.c
src/gallium/winsys/r600/drm/r600_hw_context.c
src/gallium/winsys/r600/drm/r600_priv.h

index 33aa45088a8f814a3cbd3fa76f6543897b353691..7b57fc80dc2e3963e541b169805f398d6d081e0c 100644 (file)
@@ -193,8 +193,6 @@ struct r600_block {
 };
 
 struct r600_range {
-       unsigned                start_offset;
-       unsigned                end_offset;
        struct r600_block       **blocks;
 };
 
@@ -239,9 +237,7 @@ struct r600_query {
 
 struct r600_context {
        struct radeon           *radeon;
-       unsigned                hash_size;
-       unsigned                hash_shift;
-       struct r600_range       range[256];
+       struct r600_range       *range;
        unsigned                nblocks;
        struct r600_block       **blocks;
        struct list_head        dirty;
index 0a5b1a09336dccbc3bc1ed2a4b52226c7d052c11..9dcf0a5e5728c4ece65bbfa4c83206a4d27aba48 100644 (file)
@@ -513,15 +513,18 @@ int evergreen_context_init(struct r600_context *ctx, struct radeon *radeon)
        ctx->radeon = radeon;
        LIST_INITHEAD(&ctx->query_list);
 
+       ctx->range = calloc(NUM_RANGES, sizeof(struct r600_range));
+       if (!ctx->range) {
+               r = -ENOMEM;
+               goto out_err;
+       }
+
        /* initialize hash */
-       ctx->hash_size = 19;
-       ctx->hash_shift = 11;
-       for (int i = 0; i < 256; i++) {
-               ctx->range[i].start_offset = i << ctx->hash_shift;
-               ctx->range[i].end_offset = ((i + 1) << ctx->hash_shift) - 1;
-               ctx->range[i].blocks = calloc(1 << ctx->hash_shift, sizeof(void*));
+       for (int i = 0; i < NUM_RANGES; i++) {
+               ctx->range[i].blocks = calloc(1 << HASH_SHIFT, sizeof(void*));
                if (ctx->range[i].blocks == NULL) {
-                       return -ENOMEM;
+                       r = -ENOMEM;
+                       goto out_err;
                }
        }
 
@@ -590,12 +593,12 @@ int evergreen_context_init(struct r600_context *ctx, struct radeon *radeon)
 
        /* setup block table */
        ctx->blocks = calloc(ctx->nblocks, sizeof(void*));
-       for (int i = 0, c = 0; i < 256; i++) {
-               for (int j = 0; j < (1 << ctx->hash_shift); j++) {
+       for (int i = 0, c = 0; i < NUM_RANGES; i++) {
+               for (int j = 0; j < (1 << HASH_SHIFT); j++) {
                        if (ctx->range[i].blocks[j]) {
                                assert(c < ctx->nblocks);
                                ctx->blocks[c++] = ctx->range[i].blocks[j];
-                               j += (ctx->range[i].blocks[j]->nreg << 2) - 1;
+                               j += (ctx->range[i].blocks[j]->nreg) - 1;
                        }
                }
        }
index 5eafece3fec641e10bba99bb9b5c0377db58a0a2..2bae543f114645b0f4a4cb5d251616574af996cb 100644 (file)
@@ -612,8 +612,8 @@ void r600_context_fini(struct r600_context *ctx)
        struct r600_block *block;
        struct r600_range *range;
 
-       for (int i = 0; i < 256; i++) {
-               for (int j = 0; j < (1 << ctx->hash_shift); j++) {
+       for (int i = 0; i < NUM_RANGES; i++) {
+               for (int j = 0; j < (1 << HASH_SHIFT); j++) {
                        block = ctx->range[i].blocks[j];
                        if (block) {
                                for (int k = 0, offset = block->start_offset; k < block->nreg; k++, offset += 4) {
@@ -628,6 +628,7 @@ void r600_context_fini(struct r600_context *ctx)
                }
                free(ctx->range[i].blocks);
        }
+       free(ctx->range);
        free(ctx->blocks);
        free(ctx->reloc);
        free(ctx->bo);
@@ -645,13 +646,15 @@ int r600_context_init(struct r600_context *ctx, struct radeon *radeon)
        ctx->radeon = radeon;
        LIST_INITHEAD(&ctx->query_list);
 
+       ctx->range = calloc(NUM_RANGES, sizeof(struct r600_range));
+       if (!ctx->range) {
+               r = -ENOMEM;
+               goto out_err;
+       }
+
        /* initialize hash */
-       ctx->hash_size = 19;
-       ctx->hash_shift = 11;
-       for (int i = 0; i < 256; i++) {
-               ctx->range[i].start_offset = i << ctx->hash_shift;
-               ctx->range[i].end_offset = ((i + 1) << ctx->hash_shift) - 1;
-               ctx->range[i].blocks = calloc(1 << ctx->hash_shift, sizeof(void*));
+       for (int i = 0; i < NUM_RANGES; i++) {
+               ctx->range[i].blocks = calloc(1 << HASH_SHIFT, sizeof(void*));
                if (ctx->range[i].blocks == NULL) {
                        r = -ENOMEM;
                        goto out_err;
@@ -723,8 +726,8 @@ int r600_context_init(struct r600_context *ctx, struct radeon *radeon)
 
        /* setup block table */
        ctx->blocks = calloc(ctx->nblocks, sizeof(void*));
-       for (int i = 0, c = 0; i < 256; i++) {
-               for (int j = 0, add; j < (1 << ctx->hash_shift); j++) {
+       for (int i = 0, c = 0; i < NUM_RANGES; i++) {
+               for (int j = 0, add; j < (1 << HASH_SHIFT); j++) {
                        if (ctx->range[i].blocks[j]) {
                                add = 1;
                                for (int k = 0; k < c; k++) {
@@ -736,7 +739,7 @@ int r600_context_init(struct r600_context *ctx, struct radeon *radeon)
                                if (add) {
                                        assert(c < ctx->nblocks);
                                        ctx->blocks[c++] = ctx->range[i].blocks[j];
-                                       j += (ctx->range[i].blocks[j]->nreg << 2) - 1;
+                                       j += (ctx->range[i].blocks[j]->nreg) - 1;
                                }
                        }
                }
index 2ca122ac59a18c317eb7f12a63715ce5a181212b..93c41c045240cb25c516618a92d7c0aa2497a9f9 100644 (file)
@@ -185,8 +185,17 @@ struct r600_bo *r600_bomgr_bo_create(struct r600_bomgr *mgr,
 /*
  * helpers
  */
-#define CTX_RANGE_ID(ctx, offset) (((offset) >> (ctx)->hash_shift) & 255)
-#define CTX_BLOCK_ID(ctx, offset) ((offset) & ((1 << (ctx)->hash_shift) - 1))
+
+/* each range covers 9 bits of dword space = 512 dwords = 2k bytes */
+/* there is a block entry for each register so 512 blocks */
+/* we have no registers to read/write below 0x8000 (0x2000 in dw space) */
+/* we use some fake offsets at 0x40000 to do evergreen sampler borders so take 0x42000 as a max bound*/
+#define RANGE_OFFSET_START 0x8000
+#define HASH_SHIFT 9
+#define NUM_RANGES (0x42000 - RANGE_OFFSET_START) / (4 << HASH_SHIFT) /* 128 << 9 = 64k */
+
+#define CTX_RANGE_ID(ctx, offset) ((((offset - RANGE_OFFSET_START) >> 2) >> HASH_SHIFT) & 255)
+#define CTX_BLOCK_ID(ctx, offset) (((offset - RANGE_OFFSET_START) >> 2) & ((1 << HASH_SHIFT) - 1))
 
 /*
  * radeon_bo.c