r300g: try to use color varyings for texcoords if max texcoord limit is exceeded
authorMarek Olšák <maraeo@gmail.com>
Sat, 2 Feb 2013 05:20:25 +0000 (06:20 +0100)
committerMarek Olšák <maraeo@gmail.com>
Wed, 6 Feb 2013 13:45:22 +0000 (14:45 +0100)
+35 piglits

src/gallium/drivers/r300/r300_context.h
src/gallium/drivers/r300/r300_screen.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 32b71eda4ee0e18f9ca315a317ff0dc98981f5a8..d88ba3f7ed7bbd1bad5bdfbdbf885890af833c40 100644 (file)
@@ -578,6 +578,7 @@ struct r300_context {
     int sprite_coord_enable;
     /* Whether two-sided color selection is enabled (AKA light_twoside). */
     boolean two_sided_color;
+    boolean flatshade;
     /* Whether fast color clear is enabled. */
     boolean cbzb_clear;
     /* Whether fragment shader needs to be validated. */
index 01f782c4a27c4b3be45ade4a1259d57ac217dab7..ebc8a2e958dec2c77d73e4544e9cf89c56fae943 100644 (file)
@@ -103,7 +103,6 @@ static int r300_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
         case PIPE_CAP_TEXTURE_BARRIER:
         case PIPE_CAP_TGSI_CAN_COMPACT_VARYINGS:
         case PIPE_CAP_TGSI_CAN_COMPACT_CONSTANTS:
-        case PIPE_CAP_VERTEX_COLOR_CLAMPED:
         case PIPE_CAP_USER_INDEX_BUFFERS:
         case PIPE_CAP_USER_CONSTANT_BUFFERS:
         case PIPE_CAP_DEPTH_CLIP_DISABLE: /* XXX implemented, but breaks Regnum Online */
@@ -122,6 +121,11 @@ static int r300_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
         case PIPE_CAP_TEXTURE_SWIZZLE:
             return util_format_s3tc_enabled ? r300screen->caps.dxtc_swizzle : 1;
 
+        /* We don't support color clamping on r500, so that we can use color
+         * intepolators for generic varyings. */
+        case PIPE_CAP_VERTEX_COLOR_CLAMPED:
+            return !is_r500;
+
         /* Supported on r500 only. */
         case PIPE_CAP_VERTEX_COLOR_UNCLAMPED:
         case PIPE_CAP_MIXED_COLORBUFFER_FORMATS:
index 4be23e64ce79efbbedc57316887a166e1f92d0fc..b756048c6c74a3b144205c626816c0a4631d5817 100644 (file)
@@ -42,6 +42,8 @@ struct r300_shader_semantics {
     int generic[ATTR_GENERIC_COUNT];
     int fog;
     int wpos;
+
+    int num_generic;
 };
 
 static INLINE void r300_shader_semantics_reset(
@@ -63,6 +65,8 @@ static INLINE void r300_shader_semantics_reset(
     for (i = 0; i < ATTR_GENERIC_COUNT; i++) {
         info->generic[i] = ATTR_UNUSED;
     }
+
+    info->num_generic = 0;
 }
 
 #endif
index 15ce3e00c072f1f10a5fc8b9aef8567f585344b0..19c7d4eb3228dfaf3d4d609f2bbe8c2a937da6c3 100644 (file)
@@ -1181,8 +1181,7 @@ static void* r300_create_rs_state(struct pipe_context* pipe,
     float point_texcoord_bottom = 0;/* R300_GA_POINT_T0: 0x4204 */
     float point_texcoord_right = 1; /* R300_GA_POINT_S1: 0x4208 */
     float point_texcoord_top = 0;   /* R300_GA_POINT_T1: 0x420c */
-    boolean vclamp = state->clamp_vertex_color ||
-                     !r300_context(pipe)->screen->caps.is_r500;
+    boolean vclamp = !r300_context(pipe)->screen->caps.is_r500;
     CB_LOCALS;
 
     /* Copy rasterizer state. */
@@ -1384,6 +1383,7 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state)
     int last_sprite_coord_enable = r300->sprite_coord_enable;
     boolean last_two_sided_color = r300->two_sided_color;
     boolean last_msaa_enable = r300->msaa_enable;
+    boolean last_flatshade = r300->flatshade;
 
     if (r300->draw && rs) {
         draw_set_rasterizer_state(r300->draw, &rs->rs_draw, state);
@@ -1394,18 +1394,21 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state)
         r300->sprite_coord_enable = rs->rs.sprite_coord_enable;
         r300->two_sided_color = rs->rs.light_twoside;
         r300->msaa_enable = rs->rs.multisample;
+        r300->flatshade = rs->rs.flatshade;
     } else {
         r300->polygon_offset_enabled = FALSE;
         r300->sprite_coord_enable = 0;
         r300->two_sided_color = FALSE;
         r300->msaa_enable = FALSE;
+        r300->flatshade = FALSE;
     }
 
     UPDATE_STATE(state, r300->rs_state);
     r300->rs_state.size = RS_STATE_MAIN_SIZE + (r300->polygon_offset_enabled ? 5 : 0);
 
     if (last_sprite_coord_enable != r300->sprite_coord_enable ||
-        last_two_sided_color != r300->two_sided_color) {
+        last_two_sided_color != r300->two_sided_color ||
+        last_flatshade != r300->flatshade) {
         r300_mark_atom_dirty(r300, &r300->rs_block_state);
     }
 
index 3ccf396b7418e3dd9069c1572757301fc0361b8c..1013557bde9727c5295fe7a51d69fd4d397aa763 100644 (file)
@@ -316,6 +316,7 @@ static void r300_update_rs_block(struct r300_context *r300)
     struct r300_shader_semantics *fs_inputs = &r300_fs(r300)->shader->inputs;
     struct r300_rs_block rs = {0};
     int i, col_count = 0, tex_count = 0, fp_offset = 0, count, loc = 0, tex_ptr = 0;
+    int gen_offset = 0;
     void (*rX00_rs_col)(struct r300_rs_block*, int, int, enum r300_rs_swizzle);
     void (*rX00_rs_col_write)(struct r300_rs_block*, int, int, enum r300_rs_col_write_type);
     void (*rX00_rs_tex)(struct r300_rs_block*, int, int, enum r300_rs_swizzle);
@@ -436,8 +437,60 @@ static void r300_update_rs_block(struct r300_context *r300)
         fprintf(stderr, "r300: ERROR: FS input FACE unassigned.\n");
     }
 
+    /* Re-use color varyings for texcoords if possible.
+     *
+     * The colors are interpolated as 20-bit floats (reduced precision),
+     * Use this hack only if there are too many generic varyings.
+     * (number of generic varyings + fog + wpos > 8) */
+    if (r300->screen->caps.is_r500 && !any_bcolor_used && !r300->flatshade &&
+       fs_inputs->face == ATTR_UNUSED &&
+        vs_outputs->num_generic + (vs_outputs->fog != ATTR_UNUSED) +
+        (fs_inputs->wpos != ATTR_UNUSED) > 8) {
+       for (i = 0; i < ATTR_GENERIC_COUNT && col_count < 2; i++) {
+           /* Cannot use color varyings for sprite coords. */
+           if (fs_inputs->generic[i] != ATTR_UNUSED &&
+               (r300->sprite_coord_enable & (1 << i))) {
+               break;
+           }
+
+           if (vs_outputs->generic[i] != ATTR_UNUSED) {
+               /* Set up the color in VAP. */
+               rs.vap_vsm_vtx_assm |= R300_INPUT_CNTL_COLOR;
+               rs.vap_out_vtx_fmt[0] |=
+                       R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT << col_count;
+               stream_loc_notcl[loc++] = 2 + col_count;
+
+               /* Rasterize it. */
+               rX00_rs_col(&rs, col_count, col_count, SWIZ_XYZW);
+
+               /* Write it to the FS input register if it's needed by the FS. */
+               if (fs_inputs->generic[i] != ATTR_UNUSED) {
+                   rX00_rs_col_write(&rs, col_count, fp_offset, WRITE_COLOR);
+                   fp_offset++;
+
+                   DBG(r300, DBG_RS,
+                       "r300: Rasterized generic %i redirected to color %i and written to FS.\n",
+                       i, col_count);
+               } else {
+                   DBG(r300, DBG_RS, "r300: Rasterized generic %i redirected to color %i unused.\n",
+                       i, col_count);
+               }
+               col_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->generic[i] != ATTR_UNUSED) {
+                   fp_offset++;
+
+                   DBG(r300, DBG_RS, "r300: FS input generic %i unassigned%s.\n", i);
+               }
+           }
+       }
+       gen_offset = i;
+    }
+
     /* Rasterize texture coordinates. */
-    for (i = 0; i < ATTR_GENERIC_COUNT && tex_count < 8; i++) {
+    for (i = gen_offset; i < ATTR_GENERIC_COUNT && tex_count < 8; i++) {
        boolean sprite_coord = false;
 
        if (fs_inputs->generic[i] != ATTR_UNUSED) {
index ea0621e2d3e485285b56e400bf88e0725b3478a3..33612a322f79ebf065120e8cdccc46da286db72d 100644 (file)
@@ -72,6 +72,7 @@ static void r300_shader_read_vs_outputs(
             case TGSI_SEMANTIC_GENERIC:
                 assert(index < ATTR_GENERIC_COUNT);
                 vs_outputs->generic[index] = i;
+                vs_outputs->num_generic++;
                 break;
 
             case TGSI_SEMANTIC_FOG: