i965/fs: Don't issue FB writes for bound but unwritten color targets.
authorKenneth Graunke <kenneth@whitecape.org>
Fri, 27 Feb 2015 01:45:49 +0000 (17:45 -0800)
committerKenneth Graunke <kenneth@whitecape.org>
Mon, 9 Mar 2015 23:07:04 +0000 (16:07 -0700)
We used to loop over all color attachments, and emit FB writes for each
one, even if the shader didn't write to a corresponding output variable.
Those color attachments would be filled with garbage (undefined values).

Football Manager binds a framebuffer with 4 color attachments, but draws
to it using a shader that only writes to gl_FragData[0..2].  This meant
that color attachment 3 would be filled with garbage, resulting in
rendering artifacts.  Now we skip writing to it, fixing rendering.

Writes to gl_FragColor initialize outputs[0..nr_color_regions-1] to
GRFs, while writes to gl_FragData[i] initialize outputs[i].

Thanks to Jason Ekstrand for tracking this down.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=86747
Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Jason Ekstrand <jason.ekstrand@intel.com>
Cc: mesa-stable@lists.freedesktop.org
src/mesa/drivers/dri/i965/brw_fs_visitor.cpp

index 522238759aa227a1cf4a1502c297c5d737be747c..7859fefe7ad6941906177fdc44558626917d302f 100644 (file)
@@ -3668,7 +3668,7 @@ fs_visitor::emit_fb_writes()
    brw_wm_prog_data *prog_data = (brw_wm_prog_data*) this->prog_data;
    brw_wm_prog_key *key = (brw_wm_prog_key*) this->key;
 
-   fs_inst *inst;
+   fs_inst *inst = NULL;
    if (do_dual_src) {
       this->current_annotation = ralloc_asprintf(this->mem_ctx,
                                                 "FB dual-source write");
@@ -3700,8 +3700,12 @@ fs_visitor::emit_fb_writes()
       }
 
       prog_data->dual_src_blend = true;
-   } else if (key->nr_color_regions > 0) {
+   } else {
       for (int target = 0; target < key->nr_color_regions; target++) {
+         /* Skip over outputs that weren't written. */
+         if (this->outputs[target].file == BAD_FILE)
+            continue;
+
          this->current_annotation = ralloc_asprintf(this->mem_ctx,
                                                     "FB write target %d",
                                                     target);
@@ -3714,7 +3718,9 @@ fs_visitor::emit_fb_writes()
                                      this->output_components[target]);
          inst->target = target;
       }
-   } else {
+   }
+
+   if (inst == NULL) {
       /* Even if there's no color buffers enabled, we still need to send
        * alpha out the pipeline to our null renderbuffer to support
        * alpha-testing, alpha-to-coverage, and so on.