r300g: Use a hash table to look up vertex info.
authorCorbin Simpson <MostAwesomeDude@gmail.com>
Fri, 16 Oct 2009 15:39:59 +0000 (08:39 -0700)
committerCorbin Simpson <MostAwesomeDude@gmail.com>
Fri, 16 Oct 2009 15:43:02 +0000 (08:43 -0700)
Need to move rs_block to this, too.

Also, I'm getting massive amounts of flicker for some reason; I bet we've gotta
re-re-examine PSC and friends. :C

src/gallium/drivers/r300/r300_context.c
src/gallium/drivers/r300/r300_context.h
src/gallium/drivers/r300/r300_emit.c
src/gallium/drivers/r300/r300_render.c
src/gallium/drivers/r300/r300_state_derived.c
src/gallium/drivers/r300/r300_state_derived.h

index b243f88bb5bdd256c8ffc34f02cc88df582a0724..a1156d2de6570ce6e8a43f122d73f20199afa6d7 100644 (file)
@@ -89,10 +89,23 @@ static boolean r300_draw_arrays(struct pipe_context* pipe, unsigned mode,
     return r300_draw_elements(pipe, NULL, 0, mode, start, count);
 }
 
-static void r300_destroy_context(struct pipe_context* context) {
+static enum pipe_error r300_clear_hash_table(void* key, void* value,
+                                             void* data)
+{
+    FREE(key);
+    FREE(value);
+    return PIPE_OK;
+}
+
+static void r300_destroy_context(struct pipe_context* context)
+{
     struct r300_context* r300 = r300_context(context);
     struct r300_query* query, * temp;
 
+    u_hash_table_foreach(r300->shader_hash_table, r300_clear_hash_table,
+        NULL);
+    u_hash_table_destroy(r300->shader_hash_table);
+
     draw_destroy(r300->draw);
 
     /* Free the OQ BO. */
@@ -167,6 +180,9 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
     r300->context.is_texture_referenced = r300_is_texture_referenced;
     r300->context.is_buffer_referenced = r300_is_buffer_referenced;
 
+    r300->shader_hash_table = u_hash_table_create(r300_shader_key_hash,
+        r300_shader_key_compare);
+
     r300->blend_color_state = CALLOC_STRUCT(r300_blend_color_state);
     r300->rs_block = CALLOC_STRUCT(r300_rs_block);
     r300->scissor_state = CALLOC_STRUCT(r300_scissor_state);
index 2acce0fd4a45eb4d64f4170f29f9487419b32c17..2a62c67fc73f66c779af503baccf2f95abd76c43 100644 (file)
 
 #include "tgsi/tgsi_scan.h"
 
+#include "util/u_hash_table.h"
 #include "util/u_memory.h"
 #include "util/u_simple_list.h"
 
 #include "r300_clear.h"
 #include "r300_query.h"
 #include "r300_screen.h"
+#include "r300_state_derived.h"
 #include "r300_winsys.h"
 
 struct r300_fragment_shader;
@@ -248,6 +250,12 @@ struct r300_context {
     struct r300_query *query_current;
     struct r300_query query_list;
 
+    /* Shader hash table. Used to store vertex formatting information, which
+     * depends on the combination of both currently loaded shaders. */
+    struct u_hash_table* shader_hash_table;
+    /* Vertex formatting information. */
+    struct r300_vertex_format* vertex_info;
+
     /* Various CSO state objects. */
     /* Blend state. */
     struct r300_blend_state* blend_state;
@@ -278,8 +286,6 @@ struct r300_context {
     /* Vertex buffers for Gallium. */
     struct pipe_vertex_buffer vertex_buffers[PIPE_MAX_ATTRIBS];
     int vertex_buffer_count;
-    /* Vertex information. */
-    struct r300_vertex_format vertex_info;
     /* Vertex shader. */
     struct r300_vertex_shader* vs;
     /* Viewport state. */
index f3adc0968e80557f10430eb4df98a329415719ed..e6092cda9bf75906a521294e95975625ffc202e2 100644 (file)
@@ -551,7 +551,7 @@ void r300_emit_vertex_buffer(struct r300_context* r300)
 
     DBG(r300, DBG_DRAW, "r300: Preparing vertex buffer %p for render, "
             "vertex size %d\n", r300->vbo,
-            r300->vertex_info.vinfo.size);
+            r300->vertex_info->vinfo.size);
     /* Set the pointer to our vertex buffer. The emitted values are this:
      * PACKET3 [3D_LOAD_VBPNTR]
      * COUNT   [1]
@@ -562,8 +562,8 @@ void r300_emit_vertex_buffer(struct r300_context* r300)
     BEGIN_CS(7);
     OUT_CS_PKT3(R300_PACKET3_3D_LOAD_VBPNTR, 3);
     OUT_CS(1);
-    OUT_CS(r300->vertex_info.vinfo.size |
-            (r300->vertex_info.vinfo.size << 8));
+    OUT_CS(r300->vertex_info->vinfo.size |
+            (r300->vertex_info->vinfo.size << 8));
     OUT_CS(r300->vbo_offset);
     OUT_CS_RELOC(r300->vbo, 0, RADEON_GEM_DOMAIN_GTT, 0, 0);
     END_CS;
@@ -575,30 +575,30 @@ void r300_emit_vertex_format_state(struct r300_context* r300)
     CS_LOCALS(r300);
 
     BEGIN_CS(26);
-    OUT_CS_REG(R300_VAP_VTX_SIZE, r300->vertex_info.vinfo.size);
+    OUT_CS_REG(R300_VAP_VTX_SIZE, r300->vertex_info->vinfo.size);
 
     OUT_CS_REG_SEQ(R300_VAP_VTX_STATE_CNTL, 2);
-    OUT_CS(r300->vertex_info.vinfo.hwfmt[0]);
-    OUT_CS(r300->vertex_info.vinfo.hwfmt[1]);
+    OUT_CS(r300->vertex_info->vinfo.hwfmt[0]);
+    OUT_CS(r300->vertex_info->vinfo.hwfmt[1]);
     OUT_CS_REG_SEQ(R300_VAP_OUTPUT_VTX_FMT_0, 2);
-    OUT_CS(r300->vertex_info.vinfo.hwfmt[2]);
-    OUT_CS(r300->vertex_info.vinfo.hwfmt[3]);
+    OUT_CS(r300->vertex_info->vinfo.hwfmt[2]);
+    OUT_CS(r300->vertex_info->vinfo.hwfmt[3]);
     /* for (i = 0; i < 4; i++) {
      *    debug_printf("hwfmt%d: 0x%08x\n", i,
-     *            r300->vertex_info.vinfo.hwfmt[i]);
+     *            r300->vertex_info->vinfo.hwfmt[i]);
      * } */
 
     OUT_CS_REG_SEQ(R300_VAP_PROG_STREAM_CNTL_0, 8);
     for (i = 0; i < 8; i++) {
-        OUT_CS(r300->vertex_info.vap_prog_stream_cntl[i]);
+        OUT_CS(r300->vertex_info->vap_prog_stream_cntl[i]);
         /* debug_printf("prog_stream_cntl%d: 0x%08x\n", i,
-         *        r300->vertex_info.vap_prog_stream_cntl[i]); */
+         *        r300->vertex_info->vap_prog_stream_cntl[i]); */
     }
     OUT_CS_REG_SEQ(R300_VAP_PROG_STREAM_CNTL_EXT_0, 8);
     for (i = 0; i < 8; i++) {
-        OUT_CS(r300->vertex_info.vap_prog_stream_cntl_ext[i]);
+        OUT_CS(r300->vertex_info->vap_prog_stream_cntl_ext[i]);
         /* debug_printf("prog_stream_cntl_ext%d: 0x%08x\n", i,
-         *        r300->vertex_info.vap_prog_stream_cntl_ext[i]); */
+         *        r300->vertex_info->vap_prog_stream_cntl_ext[i]); */
     }
     END_CS;
 }
index b56f7a3d1e6633ae65db8ca6d2f5558f7613c155..4e778e1e573a1f9d13234db57d0e9d483ff56a96 100644 (file)
@@ -67,7 +67,7 @@ r300_render_get_vertex_info(struct vbuf_render* render)
 
     r300_update_derived_state(r300);
 
-    return &r300->vertex_info.vinfo;
+    return &r300->vertex_info->vinfo;
 }
 
 static boolean r300_render_allocate_vertices(struct vbuf_render* render,
index f0861a9cf1d5efa681431c1b67603f48a1f6543e..53027777d68ca480d33ab958fc42ae63c77b2616 100644 (file)
 /* r300_state_derived: Various bits of state which are dependent upon
  * currently bound CSO data. */
 
+struct r300_shader_key {
+    struct r300_vertex_shader* vs;
+    struct r300_fragment_shader* fs;
+};
+
+unsigned r300_shader_key_hash(void* key) {
+    struct r300_shader_key* shader_key = (struct r300_shader_key*)key;
+    unsigned vs = (unsigned)shader_key->vs;
+    unsigned fs = (unsigned)shader_key->fs;
+
+    return (vs << 16) | (fs & 0xffff);
+}
+
+int r300_shader_key_compare(void* key1, void* key2) {
+    struct r300_shader_key* shader_key1 = (struct r300_shader_key*)key1;
+    struct r300_shader_key* shader_key2 = (struct r300_shader_key*)key2;
+
+    return (shader_key1->vs == shader_key2->vs) &&
+        (shader_key1->fs == shader_key2->fs);
+}
+
 /* Set up the vs_tab and routes. */
 static void r300_vs_tab_routes(struct r300_context* r300,
                                struct r300_vertex_format* vformat)
@@ -247,23 +268,41 @@ static void r300_vertex_psc(struct r300_context* r300,
 /* Update the vertex format. */
 static void r300_update_vertex_format(struct r300_context* r300)
 {
-    struct r300_vertex_format vformat;
+    struct r300_shader_key* key;
+    struct r300_vertex_format* vformat;
+    void* value;
     int i;
 
-    memset(&vformat, 0, sizeof(struct r300_vertex_format));
-    for (i = 0; i < 16; i++) {
-        vformat.vs_tab[i] = -1;
-        vformat.fs_tab[i] = -1;
-    }
+    key = CALLOC_STRUCT(r300_shader_key);
+    key->vs = r300->vs;
+    key->fs = r300->fs;
 
-    r300_vs_tab_routes(r300, &vformat);
+    value = u_hash_table_get(r300->shader_hash_table, (void*)key);
+    if (value) {
+        debug_printf("r300: Hash table hit! vs: %p fs: %p\n", key->vs,
+            key->fs);
+        vformat = (struct r300_vertex_format*)value;
+    } else {
+        debug_printf("r300: Hash table miss... vs: %p fs: %p\n", key->vs,
+            key->fs);
+        vformat = CALLOC_STRUCT(r300_vertex_format);
+
+        for (i = 0; i < 16; i++) {
+            vformat->vs_tab[i] = -1;
+            vformat->fs_tab[i] = -1;
+        }
+
+        r300_vs_tab_routes(r300, vformat);
+        r300_vertex_psc(r300, vformat);
 
-    r300_vertex_psc(r300, &vformat);
+        if (u_hash_table_set(r300->shader_hash_table, (void*)key,
+                (void*)vformat) != PIPE_OK) {
+            debug_printf("r300: Hash table insertion error!\n");
+        }
+    }
 
-    if (memcmp(&r300->vertex_info, &vformat,
-                sizeof(struct r300_vertex_format))) {
-        memcpy(&r300->vertex_info, &vformat,
-                sizeof(struct r300_vertex_format));
+    if (r300->vertex_info != vformat) {
+        r300->vertex_info = vformat;
         r300->dirty_state |= R300_NEW_VERTEX_FORMAT;
     }
 }
@@ -271,7 +310,7 @@ static void r300_update_vertex_format(struct r300_context* r300)
 /* Set up the mappings from GB to US, for RS block. */
 static void r300_update_fs_tab(struct r300_context* r300)
 {
-    struct r300_vertex_format* vformat = &r300->vertex_info;
+    struct r300_vertex_format* vformat = r300->vertex_info;
     struct tgsi_shader_info* info = &r300->fs->info;
     int i, cols = 0, texs = 0, cols_emitted = 0;
     int* tab = vformat->fs_tab;
@@ -337,7 +376,7 @@ static void r300_update_rs_block(struct r300_context* r300)
 {
     struct r300_rs_block* rs = r300->rs_block;
     struct tgsi_shader_info* info = &r300->fs->info;
-    int* tab = r300->vertex_info.fs_tab;
+    int* tab = r300->vertex_info->fs_tab;
     int col_count = 0, fp_offset = 0, i, tex_count = 0;
     int rs_tex_comp = 0;
     memset(rs, 0, sizeof(struct r300_rs_block));
@@ -477,10 +516,7 @@ static void r300_update_ztop(struct r300_context* r300)
 
 void r300_update_derived_state(struct r300_context* r300)
 {
-    if (r300->dirty_state &
-            (R300_NEW_FRAGMENT_SHADER | R300_NEW_VERTEX_SHADER)) {
-        r300_update_vertex_format(r300);
-    }
+    r300_update_vertex_format(r300);
 
     if (r300->dirty_state & R300_NEW_VERTEX_FORMAT) {
         r300_update_fs_tab(r300);
index 71a4a47b003662bd7aa567fdf32c4751a0765262..05ad535e2de18487f00bbfcb298948a71ab2cf6f 100644 (file)
 
 struct r300_context;
 
+unsigned r300_shader_key_hash(void* key);
+
+int r300_shader_key_compare(void* key1, void* key2);
+
 void r300_update_derived_state(struct r300_context* r300);
 
 #endif /* R300_STATE_DERIVED_H */