r300g: disable the rasterization of WPOS if it's unused by the FS
authorMarek Olšák <maraeo@gmail.com>
Thu, 24 Dec 2009 15:05:44 +0000 (16:05 +0100)
committerCorbin Simpson <MostAwesomeDude@gmail.com>
Wed, 6 Jan 2010 20:49:15 +0000 (12:49 -0800)
src/gallium/drivers/r300/r300_state.c
src/gallium/drivers/r300/r300_state_derived.c
src/gallium/drivers/r300/r300_vs.c
src/gallium/drivers/r300/r300_vs.h

index ad8e210dcd89579ca6a649135687e94d3abbebad..affd0b4591067ce605505257e7e11812355f65c3 100644 (file)
@@ -556,6 +556,10 @@ static void r300_bind_fs_state(struct pipe_context* pipe, void* shader)
     r300->fs = fs;
     r300_pick_fragment_shader(r300);
 
+    if (r300->vs && r300_vertex_shader_setup_wpos(r300)) {
+        r300->dirty_state |= R300_NEW_VERTEX_FORMAT;
+    }
+
     r300->dirty_state |= R300_NEW_FRAGMENT_SHADER | R300_NEW_FRAGMENT_SHADER_CONSTANTS;
 }
 
@@ -974,7 +978,13 @@ static void r300_bind_vs_state(struct pipe_context* pipe, void* shader)
         }
 
         r300->vs = vs;
-        r300->dirty_state |= R300_NEW_VERTEX_SHADER | R300_NEW_VERTEX_SHADER_CONSTANTS;
+        if (r300->fs) {
+            r300_vertex_shader_setup_wpos(r300);
+        }
+
+        r300->dirty_state |=
+            R300_NEW_VERTEX_SHADER | R300_NEW_VERTEX_SHADER_CONSTANTS |
+            R300_NEW_VERTEX_FORMAT;
     } else {
         draw_flush(r300->draw);
         draw_bind_vertex_shader(r300->draw,
index 242716fcccb899dc52b2034b32ff416983bf09c0..2a12a02e18a6d4640cd9be5b317c62ce0cdb280b 100644 (file)
@@ -411,23 +411,13 @@ static void r300_update_rs_block(struct r300_context* r300,
     }
 
     /* Rasterize WPOS. */
-    if (vs_outputs->wpos != ATTR_UNUSED) {
-        /* Always rasterize if it's written by the VS,
-         * otherwise it locks up. */
+    /* If the FS doesn't need it, it's not written by the VS. */
+    if (fs_inputs->wpos != ATTR_UNUSED) {
         rX00_rs_tex(rs, tex_count, tex_count, FALSE);
+        rX00_rs_tex_write(rs, tex_count, fp_offset);
 
-        /* Write it to the FS input register if it's used by the FS. */
-        if (fs_inputs->wpos != ATTR_UNUSED) {
-            rX00_rs_tex_write(rs, tex_count, fp_offset);
-            fp_offset++;
-        }
+        fp_offset++;
         tex_count++;
-    } else {
-        /* Skip the FS input register, leave it uninitialized. */
-        /* If we try to set it to (0,0,0,1), it will lock up. */
-        if (fs_inputs->wpos != ATTR_UNUSED) {
-            fp_offset++;
-        }
     }
 
     /* Rasterize at least one color, or bad things happen. */
index 57531fc554f164d68aef36783362930c121ed8d3..3512a6dc760c85c0854d1b73e80598f7a661b716 100644 (file)
@@ -22,6 +22,7 @@
  * USE OR OTHER DEALINGS IN THE SOFTWARE. */
 
 #include "r300_vs.h"
+#include "r300_fs.h"
 
 #include "r300_context.h"
 #include "r300_screen.h"
@@ -90,10 +91,10 @@ static void r300_shader_read_vs_outputs(
     }
 }
 
-static void r300_shader_vap_output_fmt(
-    struct r300_shader_semantics* vs_outputs,
-    uint* hwfmt)
+static void r300_shader_vap_output_fmt(struct r300_vertex_shader* vs)
 {
+    struct r300_shader_semantics* vs_outputs = &vs->outputs;
+    uint32_t* hwfmt = vs->hwfmt;
     int i, gen_count;
 
     /* Do the actual vertex_info setup.
@@ -146,15 +147,11 @@ static void r300_shader_vap_output_fmt(
         gen_count++;
     }
 
-    /* WPOS. */
-    if (vs_outputs->wpos != ATTR_UNUSED) {
-        hwfmt[1] |= (R300_INPUT_CNTL_TC0 << gen_count);
-        hwfmt[3] |= (4 << (3 * gen_count));
-        gen_count++;
-    }
-
     /* XXX magic */
     assert(gen_count <= 8);
+
+    /* WPOS. */
+    vs->wpos_tex_output = gen_count;
 }
 
 /* Sets up stream mapping to equivalent VS outputs if TCL is bypassed
@@ -211,9 +208,6 @@ static void r300_stream_locations_notcl(
         gen_count++;
     }
 
-    /* XXX magic */
-    assert(gen_count <= 8);
-
     for (; tabi < 16;) {
         stream_loc[tabi++] = -1;
     }
@@ -296,7 +290,6 @@ void r300_translate_vertex_shader(struct r300_context* r300,
 {
     struct r300_vertex_program_compiler compiler;
     struct tgsi_to_rc ttr;
-    boolean use_wpos = TRUE;
 
     /* Initialize. */
     r300_shader_read_vs_outputs(&vs->info, &vs->outputs);
@@ -319,15 +312,13 @@ void r300_translate_vertex_shader(struct r300_context* r300,
 
     r300_tgsi_to_rc(&ttr, vs->state.tokens);
 
-    compiler.RequiredOutputs = ~(~0 << (vs->info.num_outputs+use_wpos));
+    compiler.RequiredOutputs = ~(~0 << (vs->info.num_outputs+1));
     compiler.SetHwInputOutput = &set_vertex_inputs_outputs;
 
     /* Insert the WPOS output. */
-    if (use_wpos) {
-        r300_insert_wpos(&compiler, &vs->outputs);
-    }
+    r300_insert_wpos(&compiler, &vs->outputs);
 
-    r300_shader_vap_output_fmt(&vs->outputs, vs->hwfmt);
+    r300_shader_vap_output_fmt(vs);
     r300_stream_locations_notcl(&vs->outputs, vs->stream_loc_notcl);
 
     /* Invoke the compiler */
@@ -342,3 +333,30 @@ void r300_translate_vertex_shader(struct r300_context* r300,
     rc_destroy(&compiler.Base);
     vs->translated = TRUE;
 }
+
+boolean r300_vertex_shader_setup_wpos(struct r300_context* r300)
+{
+    struct r300_vertex_shader* vs = r300->vs;
+    int tex_output = r300->vs->wpos_tex_output;
+    uint32_t tex_fmt = R300_INPUT_CNTL_TC0 << tex_output;
+    uint32_t* hwfmt = vs->hwfmt;
+
+    if (r300->fs->inputs.wpos != ATTR_UNUSED) {
+        /* Enable WPOS in VAP. */
+        if (!(hwfmt[1] & tex_fmt)) {
+            hwfmt[1] |= tex_fmt;
+            hwfmt[3] |= (4 << (3 * tex_output));
+
+            assert(tex_output < 8);
+            return TRUE;
+        }
+    } else {
+        /* Disable WPOS in VAP. */
+        if (hwfmt[1] & tex_fmt) {
+            hwfmt[1] &= ~tex_fmt;
+            hwfmt[3] &= ~(4 << (3 * tex_output));
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
index 67e9db5366fd9ad6a85eeea5c859d1091f606773..18cfeee3cd457e62f84414e455cb097d42caa654 100644 (file)
@@ -43,6 +43,9 @@ struct r300_vertex_shader {
     /* Stream locations for SWTCL or if TCL is bypassed. */
     int stream_loc_notcl[16];
 
+    /* Output stream location for WPOS. */
+    int wpos_tex_output;
+
     /* Has this shader been translated yet? */
     boolean translated;
 
@@ -53,4 +56,7 @@ struct r300_vertex_shader {
 void r300_translate_vertex_shader(struct r300_context* r300,
                                   struct r300_vertex_shader* vs);
 
+/* Return TRUE if VAP (hwfmt) needs to be re-emitted. */
+boolean r300_vertex_shader_setup_wpos(struct r300_context* r300);
+
 #endif /* R300_VS_H */