r300g: add WPOS
authorMarek Olšák <maraeo@gmail.com>
Thu, 24 Dec 2009 02:10:33 +0000 (03:10 +0100)
committerCorbin Simpson <MostAwesomeDude@gmail.com>
Wed, 6 Jan 2010 20:49:15 +0000 (12:49 -0800)
src/gallium/drivers/r300/r300_emit.c
src/gallium/drivers/r300/r300_fs.c
src/gallium/drivers/r300/r300_shader_semantics.h
src/gallium/drivers/r300/r300_state.c
src/gallium/drivers/r300/r300_state_derived.c
src/gallium/drivers/r300/r300_vs.c

index 596ec21bc0e72087002bd709e1e82e50baa20fd0..30a1000c29413e045a1788e8ac70000279c5c03f 100644 (file)
@@ -165,6 +165,28 @@ static const float * get_shader_constant(
                     vec[3] = 0;
                     break;
 
+                case RC_STATE_R300_VIEWPORT_SCALE:
+                    if (r300->rs_state->enable_vte) {
+                        vec[0] = r300->viewport_state->xscale;
+                        vec[1] = r300->viewport_state->yscale;
+                        vec[2] = r300->viewport_state->zscale;
+                    } else {
+                        vec[0] = 1;
+                        vec[1] = 1;
+                        vec[2] = 1;
+                    }
+                    break;
+
+                case RC_STATE_R300_VIEWPORT_OFFSET:
+                    if (r300->rs_state->enable_vte) {
+                        vec[0] = r300->viewport_state->xoffset;
+                        vec[1] = r300->viewport_state->yoffset;
+                        vec[2] = r300->viewport_state->zoffset;
+                    } else {
+                        /* Zeros. */
+                    }
+                    break;
+
                 default:
                     debug_printf("r300: Implementation error: "
                         "Unknown RC_CONSTANT type %d\n", constant->u.State[0]);
index 4e1b61ca409bced507670f1235e91908e35afbc4..60ea9c171d5d9eef7090986dcf8080ce4fb1d8f7 100644 (file)
@@ -63,6 +63,11 @@ void r300_shader_read_fs_inputs(struct tgsi_shader_info* info,
                 fs_inputs->fog = i;
                 break;
 
+            case TGSI_SEMANTIC_POSITION:
+                assert(index == 0);
+                fs_inputs->wpos = i;
+                break;
+
             default:
                 assert(0);
         }
@@ -114,6 +119,9 @@ static void allocate_hardware_inputs(
     if (inputs->fog != ATTR_UNUSED) {
         allocate(mydata, inputs->fog, reg++);
     }
+    if (inputs->wpos != ATTR_UNUSED) {
+        allocate(mydata, inputs->wpos, reg++);
+    }
 }
 
 static void get_compare_state(
@@ -144,6 +152,7 @@ static void r300_translate_fragment_shader(
     struct r300_fragment_shader* fs = r300->fs;
     struct r300_fragment_program_compiler compiler;
     struct tgsi_to_rc ttr;
+    int wpos = fs->inputs.wpos;
 
     /* Setup the compiler. */
     memset(&compiler, 0, sizeof(compiler));
@@ -171,6 +180,18 @@ static void r300_translate_fragment_shader(
 
     fs->shadow_samplers = compiler.Base.Program.ShadowSamplers;
 
+    /**
+     * Transform the program to support WPOS.
+     *
+     * Introduce a small fragment at the start of the program that will be
+     * the only code that directly reads the WPOS input.
+     * All other code pieces that reference that input will be rewritten
+     * to read from a newly allocated temporary. */
+    if (wpos != ATTR_UNUSED) {
+        /* Moving the input to some other reg is not really necessary. */
+        rc_transform_fragment_wpos(&compiler.Base, wpos, wpos, TRUE);
+    }
+
     /* Invoke the compiler */
     r3xx_compile_fragment_program(&compiler);
     if (compiler.Base.Error) {
index 85184e2cfd7201228da205b8c1ba5902d3a3f7aa..6796841b29bbe74abcda5fd30f523748f3e9fe73 100644 (file)
@@ -40,6 +40,7 @@ struct r300_shader_semantics {
     int bcolor[ATTR_COLOR_COUNT];
     int generic[ATTR_GENERIC_COUNT];
     int fog;
+    int wpos;
 };
 
 static INLINE void r300_shader_semantics_reset(
@@ -50,6 +51,7 @@ static INLINE void r300_shader_semantics_reset(
     info->pos = ATTR_UNUSED;
     info->psize = ATTR_UNUSED;
     info->fog = ATTR_UNUSED;
+    info->wpos = ATTR_UNUSED;
 
     for (i = 0; i < ATTR_COLOR_COUNT; i++) {
         info->color[i] = ATTR_UNUSED;
index 872a393321d2fbfb816fc469bd8daae3b83fa5c9..ad8e210dcd89579ca6a649135687e94d3abbebad 100644 (file)
@@ -719,6 +719,9 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state)
     r300->dirty_state |= R300_NEW_RS_BLOCK;
     r300->dirty_state |= R300_NEW_SCISSOR;
     r300->dirty_state |= R300_NEW_VIEWPORT;
+    if (r300->fs && r300->fs->inputs.wpos != ATTR_UNUSED) {
+        r300->dirty_state |= R300_NEW_FRAGMENT_SHADER_CONSTANTS;
+    }
 }
 
 /* Free rasterizer state. */
@@ -897,6 +900,9 @@ static void r300_set_viewport_state(struct pipe_context* pipe,
     }
 
     r300->dirty_state |= R300_NEW_VIEWPORT;
+    if (r300->fs && r300->fs->inputs.wpos != ATTR_UNUSED) {
+        r300->dirty_state |= R300_NEW_FRAGMENT_SHADER_CONSTANTS;
+    }
 }
 
 static void r300_set_vertex_buffers(struct pipe_context* pipe,
index 727ae7ade6d57e7e62681e0af55a7ebdf4d99b40..242716fcccb899dc52b2034b32ff416983bf09c0 100644 (file)
@@ -410,6 +410,26 @@ 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. */
+        rX00_rs_tex(rs, tex_count, tex_count, FALSE);
+
+        /* 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++;
+        }
+        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. */
     if (col_count == 0 && tex_count == 0) {
         rX00_rs_col(rs, 0, 0, TRUE);
index c4ed0d712f9cb84c6e3d15b5ed33f1207f27ceee..57531fc554f164d68aef36783362930c121ed8d3 100644 (file)
@@ -33,6 +33,8 @@
 
 #include "radeon_compiler.h"
 
+#include "util/u_math.h"
+
 /* Convert info about VS output semantics into r300_shader_semantics. */
 static void r300_shader_read_vs_outputs(
     struct tgsi_shader_info* info,
@@ -144,6 +146,13 @@ 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);
 }
@@ -195,6 +204,13 @@ static void r300_stream_locations_notcl(
         gen_count++;
     }
 
+    /* WPOS. */
+    if (vs_outputs->wpos != ATTR_UNUSED) {
+        assert(tabi < 16);
+        stream_loc[tabi++] = 6 + gen_count;
+        gen_count++;
+    }
+
     /* XXX magic */
     assert(gen_count <= 8);
 
@@ -246,6 +262,33 @@ static void set_vertex_inputs_outputs(struct r300_vertex_program_compiler * c)
     if (outputs->fog != ATTR_UNUSED) {
         c->code->outputs[outputs->fog] = reg++;
     }
+
+    /* WPOS. */
+    if (outputs->wpos != ATTR_UNUSED) {
+        c->code->outputs[outputs->wpos] = reg++;
+    }
+}
+
+static void r300_insert_wpos(struct r300_vertex_program_compiler* c,
+                             struct r300_shader_semantics* outputs)
+{
+    int i, lastOutput = 0;
+
+    /* Find the max output index. */
+    lastOutput = MAX2(lastOutput, outputs->psize);
+    for (i = 0; i < ATTR_COLOR_COUNT; i++) {
+        lastOutput = MAX2(lastOutput, outputs->color[i]);
+        lastOutput = MAX2(lastOutput, outputs->bcolor[i]);
+    }
+    for (i = 0; i < ATTR_GENERIC_COUNT; i++) {
+        lastOutput = MAX2(lastOutput, outputs->generic[i]);
+    }
+    lastOutput = MAX2(lastOutput, outputs->fog);
+
+    /* Set WPOS after the last output. */
+    lastOutput++;
+    rc_copy_output(&c->Base, 0, lastOutput); /* out[lastOutput] = out[0]; */
+    outputs->wpos = lastOutput;
 }
 
 void r300_translate_vertex_shader(struct r300_context* r300,
@@ -253,11 +296,10 @@ 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);
-    r300_shader_vap_output_fmt(&vs->outputs, vs->hwfmt);
-    r300_stream_locations_notcl(&vs->outputs, vs->stream_loc_notcl);
 
     /* Setup the compiler */
     rc_init(&compiler.Base);
@@ -277,9 +319,17 @@ void r300_translate_vertex_shader(struct r300_context* r300,
 
     r300_tgsi_to_rc(&ttr, vs->state.tokens);
 
-    compiler.RequiredOutputs = ~(~0 << vs->info.num_outputs);
+    compiler.RequiredOutputs = ~(~0 << (vs->info.num_outputs+use_wpos));
     compiler.SetHwInputOutput = &set_vertex_inputs_outputs;
 
+    /* Insert the WPOS output. */
+    if (use_wpos) {
+        r300_insert_wpos(&compiler, &vs->outputs);
+    }
+
+    r300_shader_vap_output_fmt(&vs->outputs, vs->hwfmt);
+    r300_stream_locations_notcl(&vs->outputs, vs->stream_loc_notcl);
+
     /* Invoke the compiler */
     r3xx_compile_vertex_program(&compiler);
     if (compiler.Base.Error) {