i965/msaa: Set SURFACE_STATE properly when CMS MSAA is in use.
authorPaul Berry <stereotype441@gmail.com>
Tue, 3 Jul 2012 18:36:39 +0000 (11:36 -0700)
committerPaul Berry <stereotype441@gmail.com>
Wed, 11 Jul 2012 22:14:49 +0000 (15:14 -0700)
When a buffer using Gen7's CMS MSAA layout is bound to a texture or a
render target, the SURFACE_STATE structure needs to point to the MCS
buffer and to indicate its pitch.  This patch updates the functions
that emit SURFACE_STATE to handle CMS layout properly.

Reviewed-by: Chad Versace <chad.versace@linux.intel.com>
src/mesa/drivers/dri/i965/brw_state.h
src/mesa/drivers/dri/i965/gen7_blorp.cpp
src/mesa/drivers/dri/i965/gen7_wm_surface_state.c

index 31853eae051f12d56ac239f50c2489382d880baf..1c70db29e38088ad34909c8a768742042b6f87eb 100644 (file)
@@ -201,6 +201,11 @@ GLuint translate_tex_format(gl_format mesa_format,
 void gen7_set_surface_tiling(struct gen7_surface_state *surf, uint32_t tiling);
 void gen7_set_surface_num_multisamples(struct gen7_surface_state *surf,
                                        unsigned num_samples);
+void gen7_set_surface_mcs_info(struct brw_context *brw,
+                               struct gen7_surface_state *surf,
+                               uint32_t surf_offset,
+                               const struct intel_mipmap_tree *mcs_mt,
+                               bool is_render_target);
 void gen7_check_surface_setup(struct gen7_surface_state *surf,
                               bool is_render_target);
 void gen7_init_vtable_surface_functions(struct brw_context *brw);
index ec6312078b7da084f1de4f382ec74fc0e08b2f18..f087dbdc66abb1b6962ad540beeb8ec83fed651d 100644 (file)
@@ -181,6 +181,10 @@ gen7_blorp_emit_surface_state(struct brw_context *brw,
    surf->ss3.pitch = pitch_bytes - 1;
 
    gen7_set_surface_num_multisamples(surf, surface->num_samples);
+   if (surface->msaa_layout == INTEL_MSAA_LAYOUT_CMS) {
+      gen7_set_surface_mcs_info(brw, surf, wm_surf_offset,
+                                surface->mt->mcs_mt, is_render_target);
+   }
 
    if (intel->is_haswell) {
       surf->ss7.shader_chanel_select_r = HSW_SCS_RED;
index 52312c9787cfeb86e8494b677d2af0bd3f5c99fd..f0370268be8c383a278050cac38825114551a8d2 100644 (file)
@@ -68,6 +68,46 @@ gen7_set_surface_num_multisamples(struct gen7_surface_state *surf,
 }
 
 
+void
+gen7_set_surface_mcs_info(struct brw_context *brw,
+                          struct gen7_surface_state *surf,
+                          uint32_t surf_offset,
+                          const struct intel_mipmap_tree *mcs_mt,
+                          bool is_render_target)
+{
+   /* From the Ivy Bridge PRM, Vol4 Part1 p76, "MCS Base Address":
+    *
+    *     "The MCS surface must be stored as Tile Y."
+    */
+   assert(mcs_mt->region->tiling == I915_TILING_Y);
+
+   /* Compute the pitch in units of tiles.  To do this we need to divide the
+    * pitch in bytes by 128, since a single Y-tile is 128 bytes wide.
+    */
+   unsigned pitch_bytes = mcs_mt->region->pitch * mcs_mt->cpp;
+   unsigned pitch_tiles = pitch_bytes / 128;
+
+   /* The upper 20 bits of surface state DWORD 6 are the upper 20 bits of the
+    * GPU address of the MCS buffer; the lower 12 bits contain other control
+    * information.  Since buffer addresses are always on 4k boundaries (and
+    * thus have their lower 12 bits zero), we can use an ordinary reloc to do
+    * the necessary address translation.
+    */
+   assert ((mcs_mt->region->bo->offset & 0xfff) == 0);
+   surf->ss6.mcs_enabled.mcs_enable = 1;
+   surf->ss6.mcs_enabled.mcs_surface_pitch = pitch_tiles - 1;
+   surf->ss6.mcs_enabled.mcs_base_address = mcs_mt->region->bo->offset >> 12;
+   drm_intel_bo_emit_reloc(brw->intel.batch.bo,
+                           surf_offset +
+                           offsetof(struct gen7_surface_state, ss6),
+                           mcs_mt->region->bo,
+                           surf->ss6.raw_data & 0xfff,
+                           is_render_target ? I915_GEM_DOMAIN_RENDER
+                           : I915_GEM_DOMAIN_SAMPLER,
+                           is_render_target ? I915_GEM_DOMAIN_RENDER : 0);
+}
+
+
 void
 gen7_check_surface_setup(struct gen7_surface_state *surf,
                          bool is_render_target)
@@ -452,6 +492,11 @@ gen7_update_renderbuffer_surface(struct brw_context *brw,
 
    gen7_set_surface_num_multisamples(surf, irb->mt->num_samples);
 
+   if (irb->mt->msaa_layout == INTEL_MSAA_LAYOUT_CMS) {
+      gen7_set_surface_mcs_info(brw, surf, brw->wm.surf_offset[unit],
+                                irb->mt->mcs_mt, true /* is_render_target */);
+   }
+
    if (intel->is_haswell) {
       surf->ss7.shader_chanel_select_r = HSW_SCS_RED;
       surf->ss7.shader_chanel_select_g = HSW_SCS_GREEN;