svga: implement TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS
authorBrian Paul <brianp@vmware.com>
Fri, 17 Jan 2014 02:32:47 +0000 (18:32 -0800)
committerBrian Paul <brianp@vmware.com>
Tue, 21 Jan 2014 18:53:51 +0000 (10:53 -0800)
Fixes several colorbuffer tests, including piglit "fbo-drawbuffers-none"
for "gl_FragColor" and "glDrawPixels" cases.

v2: rework patch to only avoid creating extra shader variants when
TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS is not specified.  Per Jose.
Use a write_color0_to_n_cbufs key field to replicate color0 to N
color buffers only when N > 0 and WRITES_ALL_CBUFS is set.

Reviewed-by: José Fonseca <jfonseca@vmware.com>
src/gallium/drivers/svga/svga_state_fs.c
src/gallium/drivers/svga/svga_tgsi.h
src/gallium/drivers/svga/svga_tgsi_decl_sm30.c
src/gallium/drivers/svga/svga_tgsi_insn.c

index 51d0eb5bacbc2549ab55c5c627d2b44effce4383..1e9fb43f8686d51d17745895bf40fc788ee504aa 100644 (file)
@@ -276,6 +276,12 @@ make_fs_key(const struct svga_context *svga,
    key->sprite_origin_lower_left = (svga->curr.rast->templ.sprite_coord_mode
                                     == PIPE_SPRITE_COORD_LOWER_LEFT);
 
+   /* SVGA_NEW_FRAME_BUFFER */
+   if (fs->base.info.color0_writes_all_cbufs) {
+      /* Replicate color0 output to N colorbuffers */
+      key->write_color0_to_n_cbufs = svga->curr.framebuffer.nr_cbufs;
+   }
+
    return PIPE_OK;
 }
 
@@ -296,6 +302,7 @@ emit_hw_fs(struct svga_context *svga, unsigned dirty)
     * SVGA_NEW_RAST
     * SVGA_NEW_NEED_SWTNL
     * SVGA_NEW_SAMPLER
+    * SVGA_NEW_FRAME_BUFFER
     */
    ret = make_fs_key( svga, fs, &key );
    if (ret != PIPE_OK)
@@ -335,6 +342,7 @@ struct svga_tracked_state svga_hw_fs =
     SVGA_NEW_NEED_SWTNL |
     SVGA_NEW_RAST |
     SVGA_NEW_SAMPLER |
+    SVGA_NEW_FRAME_BUFFER |
     SVGA_NEW_BLEND),
    emit_hw_fs
 };
index 0e06dbf9919437baf20dbc405af203e0afbddf3f..591dd6a3917943e9439dd45182114346f7344864 100644 (file)
@@ -56,6 +56,7 @@ struct svga_fs_compile_key
    unsigned light_twoside:1;
    unsigned front_ccw:1;
    unsigned white_fragments:1;
+   unsigned write_color0_to_n_cbufs:3;
    unsigned num_textures:8;
    unsigned num_unnormalized_coords:8;
    unsigned sprite_origin_lower_left:1;
index e0a30a5248e380bab40792a2c2c2bbb32a840730..137afd605830b92c8da7b32601ebee4eb18fd6c4 100644 (file)
@@ -327,14 +327,35 @@ ps30_output(struct svga_shader_emitter *emit,
 {
    switch (semantic.Name) {
    case TGSI_SEMANTIC_COLOR:
-      if (emit->unit == PIPE_SHADER_FRAGMENT &&
-          emit->key.fkey.white_fragments) {
-
-         emit->output_map[idx] = dst_register( SVGA3DREG_TEMP,
-                                               emit->nr_hw_temp++ );
-         emit->temp_color_output[idx] = emit->output_map[idx];
-         emit->true_color_output[idx] = dst_register(SVGA3DREG_COLOROUT, 
-                                                     semantic.Index);
+      if (emit->unit == PIPE_SHADER_FRAGMENT) {
+         if (emit->key.fkey.white_fragments) {
+            /* Used for XOR logicop mode */
+            emit->output_map[idx] = dst_register( SVGA3DREG_TEMP,
+                                                  emit->nr_hw_temp++ );
+            emit->temp_color_output[idx] = emit->output_map[idx];
+            emit->true_color_output[idx] = dst_register(SVGA3DREG_COLOROUT, 
+                                                        semantic.Index);
+         }
+         else if (emit->key.fkey.write_color0_to_n_cbufs) {
+            /* We'll write color output [0] to all render targets.
+             * Prepare all the output registers here, but only when the
+             * semantic.Index == 0 so we don't do this more than once.
+             */
+            if (semantic.Index == 0) {
+               unsigned i;
+               for (i = 0; i < emit->key.fkey.write_color0_to_n_cbufs; i++) {
+                  emit->output_map[i] = dst_register(SVGA3DREG_TEMP,
+                                                     emit->nr_hw_temp++);
+                  emit->temp_color_output[i] = emit->output_map[i];
+                  emit->true_color_output[i] = dst_register(SVGA3DREG_COLOROUT,
+                                                            i);
+               }
+            }
+         }
+         else {
+            emit->output_map[idx] =
+               dst_register(SVGA3DREG_COLOROUT, semantic.Index);
+         }
       }
       else {
          emit->output_map[idx] = dst_register( SVGA3DREG_COLOROUT, 
index 2143546229370abd8829d0f0dde751ca36bf3348..ce00da6fc0b4e9f6fd15aa177cb02023481e7eda 100644 (file)
@@ -3074,6 +3074,15 @@ emit_ps_postamble(struct svga_shader_emitter *emit)
                              one ))
                return FALSE;
          }
+         else if (emit->unit == PIPE_SHADER_FRAGMENT &&
+                  i < emit->key.fkey.write_color0_to_n_cbufs) {
+            /* Write temp color output [0] to true output [i] */
+            if (!submit_op1(emit, inst_token(SVGA3DOP_MOV),
+                            emit->true_color_output[i],
+                            src(emit->temp_color_output[0]))) {
+               return FALSE;
+            }
+         }
          else {
             if (!submit_op1( emit,
                              inst_token(SVGA3DOP_MOV),