aboutsummaryrefslogtreecommitdiffstats
path: root/src/mesa/drivers/dri/i965/brw_misc_state.c
diff options
context:
space:
mode:
authorEric Anholt <[email protected]>2012-11-04 12:47:02 -0800
committerEric Anholt <[email protected]>2012-11-19 15:07:22 -0800
commit52ee1a7269b84b60558760655a4c722d827703d4 (patch)
tree0af5371769efa438394dd1210d35a639dec49d9f /src/mesa/drivers/dri/i965/brw_misc_state.c
parent9ec6a54ba94264d4d6c6ddbced2144a882a23cfa (diff)
i965: Move all the depth/stencil/hiz offset logic into the workaround.
Given that we have the mask information here (assuming the rebase is to the same tiling, which is safe), we can just save a set of miptrees and offsets and the global intra-tile offset in the context and cut out a bunch of logic. This will also save emitting the next fix I need to do twice. Acked-by: Chad Versace <[email protected]>
Diffstat (limited to 'src/mesa/drivers/dri/i965/brw_misc_state.c')
-rw-r--r--src/mesa/drivers/dri/i965/brw_misc_state.c221
1 files changed, 113 insertions, 108 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_misc_state.c b/src/mesa/drivers/dri/i965/brw_misc_state.c
index 8e80d70b897..f6cfdc41b11 100644
--- a/src/mesa/drivers/dri/i965/brw_misc_state.c
+++ b/src/mesa/drivers/dri/i965/brw_misc_state.c
@@ -329,7 +329,7 @@ brw_workaround_depthstencil_alignment(struct brw_context *brw)
struct intel_renderbuffer *stencil_irb = intel_get_renderbuffer(fb, BUFFER_STENCIL);
struct intel_mipmap_tree *depth_mt = NULL;
struct intel_mipmap_tree *stencil_mt = NULL;
- uint32_t depth_tile_x = 0, depth_tile_y = 0;
+ uint32_t tile_x = 0, tile_y = 0, stencil_tile_x = 0, stencil_tile_y = 0;
if (depth_irb)
depth_mt = depth_irb->mt;
@@ -341,18 +341,22 @@ brw_workaround_depthstencil_alignment(struct brw_context *brw)
&tile_mask_x, &tile_mask_y);
if (depth_irb) {
- depth_tile_x = depth_irb->draw_x & tile_mask_x;
- depth_tile_y = depth_irb->draw_y & tile_mask_y;
+ tile_x = depth_irb->draw_x & tile_mask_x;
+ tile_y = depth_irb->draw_y & tile_mask_y;
- /* The low 3 bits of x and y tile offset are ignored by the hardware.
- * Rebase if they're set, so that we can actually render to the buffer.
+ /* According to the Sandy Bridge PRM, volume 2 part 1, pp326-327
+ * (3DSTATE_DEPTH_BUFFER dw5), in the documentation for "Depth
+ * Coordinate Offset X/Y":
+ *
+ * "The 3 LSBs of both offsets must be zero to ensure correct
+ * alignment"
*/
- if (depth_tile_x & 7 || depth_tile_y & 7)
+ if (tile_x & 7 || tile_y & 7)
rebase_depth = true;
/* We didn't even have intra-tile offsets before g45. */
if (intel->gen == 4 && !intel->is_g4x) {
- if (depth_tile_x || depth_tile_y)
+ if (tile_x || tile_y)
rebase_depth = true;
}
@@ -368,8 +372,8 @@ brw_workaround_depthstencil_alignment(struct brw_context *brw)
intel_renderbuffer_set_draw_offset(stencil_irb);
}
- depth_tile_x = depth_irb->draw_x & tile_mask_x;
- depth_tile_y = depth_irb->draw_y & tile_mask_y;
+ tile_x = depth_irb->draw_x & tile_mask_x;
+ tile_y = depth_irb->draw_y & tile_mask_y;
}
if (stencil_irb) {
@@ -381,8 +385,8 @@ brw_workaround_depthstencil_alignment(struct brw_context *brw)
* post-stencil depth test will also rebase depth to try to match it
* up).
*/
- if (depth_tile_x != stencil_tile_x ||
- depth_tile_y != stencil_tile_y) {
+ if (tile_x != stencil_tile_x ||
+ tile_y != stencil_tile_y) {
rebase_stencil = true;
}
}
@@ -390,8 +394,8 @@ brw_workaround_depthstencil_alignment(struct brw_context *brw)
/* If we have (just) stencil, check it for ignored low bits as well */
if (stencil_irb) {
- uint32_t stencil_tile_x = stencil_irb->draw_x & tile_mask_x;
- uint32_t stencil_tile_y = stencil_irb->draw_y & tile_mask_y;
+ stencil_tile_x = stencil_irb->draw_x & tile_mask_x;
+ stencil_tile_y = stencil_irb->draw_y & tile_mask_y;
if (stencil_tile_x & 7 || stencil_tile_y & 7)
rebase_stencil = true;
@@ -405,24 +409,96 @@ brw_workaround_depthstencil_alignment(struct brw_context *brw)
if (rebase_stencil) {
intel_renderbuffer_move_to_temp(intel, stencil_irb);
- uint32_t stencil_tile_x = stencil_irb->draw_x & tile_mask_x;
- uint32_t stencil_tile_y = stencil_irb->draw_y & tile_mask_y;
+ stencil_tile_x = stencil_irb->draw_x & tile_mask_x;
+ stencil_tile_y = stencil_irb->draw_y & tile_mask_y;
if (depth_irb && depth_irb->mt == stencil_mt) {
intel_miptree_reference(&depth_irb->mt, stencil_irb->mt);
intel_renderbuffer_set_draw_offset(depth_irb);
} else if (depth_irb && !rebase_depth) {
- if (depth_tile_x != stencil_tile_x ||
- depth_tile_y != stencil_tile_y) {
+ if (tile_x != stencil_tile_x ||
+ tile_y != stencil_tile_y) {
intel_renderbuffer_move_to_temp(intel, depth_irb);
+ tile_x = depth_irb->draw_x & tile_mask_x;
+ tile_y = depth_irb->draw_y & tile_mask_y;
+
if (stencil_irb && stencil_irb->mt == depth_mt) {
intel_miptree_reference(&stencil_irb->mt, depth_irb->mt);
intel_renderbuffer_set_draw_offset(stencil_irb);
}
+
+ WARN_ONCE(stencil_tile_x != tile_x ||
+ stencil_tile_y != tile_y,
+ "Rebased stencil tile offset (%d,%d) doesn't match depth "
+ "tile offset (%d,%d).\n",
+ stencil_tile_x, stencil_tile_y,
+ tile_x, tile_y);
}
}
}
+
+ if (!depth_irb) {
+ tile_x = stencil_tile_x;
+ tile_y = stencil_tile_y;
+ }
+
+ /* While we just tried to get everything aligned, we may have failed to do
+ * so in the case of rendering to array or 3D textures, where nonzero faces
+ * will still have an offset post-rebase. At least give an informative
+ * warning.
+ */
+ WARN_ONCE((tile_x & 7) || (tile_y & 7),
+ "Depth/stencil buffer needs alignment to 8-pixel boundaries.\n"
+ "Truncating offset, bad rendering may occur.\n");
+ tile_x &= ~7;
+ tile_y &= ~7;
+
+ /* Now, after rebasing, save off the new dephtstencil state so the hardware
+ * packets can just dereference that without re-calculating tile offsets.
+ */
+ brw->depthstencil.tile_x = tile_x;
+ brw->depthstencil.tile_y = tile_y;
+ brw->depthstencil.depth_offset = 0;
+ brw->depthstencil.stencil_offset = 0;
+ brw->depthstencil.hiz_offset = 0;
+ brw->depthstencil.depth_mt = NULL;
+ brw->depthstencil.stencil_mt = NULL;
+ brw->depthstencil.hiz_mt = NULL;
+ if (depth_irb) {
+ depth_mt = depth_irb->mt;
+ brw->depthstencil.depth_mt = depth_mt;
+ brw->depthstencil.depth_offset =
+ intel_region_get_aligned_offset(depth_mt->region,
+ depth_irb->draw_x & ~tile_mask_x,
+ depth_irb->draw_y & ~tile_mask_y,
+ false);
+ if (depth_mt->hiz_mt) {
+ brw->depthstencil.hiz_mt = depth_mt->hiz_mt;
+ brw->depthstencil.hiz_offset =
+ intel_region_get_aligned_offset(depth_mt->region,
+ depth_irb->draw_x & ~tile_mask_x,
+ (depth_irb->draw_y & ~tile_mask_y) /
+ 2,
+ false);
+ }
+ }
+ if (stencil_irb) {
+ stencil_mt = stencil_irb->mt;
+ if (stencil_mt->stencil_mt)
+ stencil_mt = stencil_mt->stencil_mt;
+
+ brw->depthstencil.stencil_mt = stencil_mt;
+ if (stencil_mt->format == MESA_FORMAT_S8) {
+ /* Note: we can't compute the stencil offset using
+ * intel_region_get_aligned_offset(), because stencil_region claims
+ * that the region is untiled even though it's W tiled.
+ */
+ brw->depthstencil.stencil_offset =
+ (stencil_irb->draw_y & ~tile_mask_y) * stencil_mt->region->pitch +
+ (stencil_irb->draw_x & ~tile_mask_x) * 64;
+ }
+ }
}
static void emit_depthbuffer(struct brw_context *brw)
@@ -433,19 +509,16 @@ static void emit_depthbuffer(struct brw_context *brw)
/* _NEW_BUFFERS */
struct intel_renderbuffer *depth_irb = intel_get_renderbuffer(fb, BUFFER_DEPTH);
struct intel_renderbuffer *stencil_irb = intel_get_renderbuffer(fb, BUFFER_STENCIL);
- struct intel_mipmap_tree *depth_mt = NULL;
- struct intel_mipmap_tree *stencil_mt = NULL;
- struct intel_region *hiz_region = NULL;
+ struct intel_mipmap_tree *depth_mt = brw->depthstencil.depth_mt;
+ struct intel_mipmap_tree *stencil_mt = brw->depthstencil.stencil_mt;
+ struct intel_mipmap_tree *hiz_mt = brw->depthstencil.hiz_mt;
+ uint32_t tile_x = brw->depthstencil.tile_x;
+ uint32_t tile_y = brw->depthstencil.tile_y;
unsigned int len;
bool separate_stencil = false;
- if (depth_irb){
- depth_mt = depth_irb->mt;
- if (depth_mt &&
- depth_mt->hiz_mt) {
- hiz_region = depth_irb->mt->hiz_mt->region;
- }
- }
+ if (stencil_mt && stencil_mt->format == MESA_FORMAT_S8)
+ separate_stencil = true;
/* 3DSTATE_DEPTH_BUFFER, 3DSTATE_STENCIL_BUFFER are both
* non-pipelined state that will need the PIPE_CONTROL workaround.
@@ -455,54 +528,6 @@ static void emit_depthbuffer(struct brw_context *brw)
intel_emit_depth_stall_flushes(intel);
}
- /* Find the real separate stencil mt if present. */
- if (stencil_irb) {
- stencil_mt = stencil_irb->mt;
- if (stencil_mt->stencil_mt)
- stencil_mt = stencil_mt->stencil_mt;
-
- if (stencil_mt->format == MESA_FORMAT_S8) {
- separate_stencil = true;
- }
- }
-
- uint32_t tile_mask_x, tile_mask_y;
- brw_get_depthstencil_tile_masks(depth_mt, stencil_mt,
- &tile_mask_x, &tile_mask_y);
-
- /* The intra-tile offsets should already have been forced into agreement by
- * gen7_workaround_depthstencil_alignment().
- */
- uint32_t tile_x = 0, tile_y = 0;
- if (depth_mt) {
- tile_x = depth_irb->draw_x & tile_mask_x;
- tile_y = depth_irb->draw_y & tile_mask_y;
-
- if (stencil_mt) {
- assert((stencil_irb->draw_x & tile_mask_x) == tile_x);
- assert((stencil_irb->draw_y & tile_mask_y) == tile_y);
- }
- } else if (stencil_mt) {
- tile_x = stencil_irb->draw_x & tile_mask_x;
- tile_y = stencil_irb->draw_y & tile_mask_y;
- }
-
- /* According to the Sandy Bridge PRM, volume 2 part 1, pp326-327
- * (3DSTATE_DEPTH_BUFFER dw5), in the documentation for "Depth
- * Coordinate Offset X/Y":
- *
- * "The 3 LSBs of both offsets must be zero to ensure correct
- * alignment"
- *
- * This should already have been corrected by
- * gen6_workaround_depthstencil_alignment.
- */
- WARN_ONCE((tile_x & 7) || (tile_y & 7),
- "Depth/stencil buffer needs alignment to 8-pixel boundaries.\n"
- "Truncating offset, bad rendering may occur.\n");
- tile_x &= ~7;
- tile_y &= ~7;
-
/* If there's a packed depth/stencil bound to stencil only, we need to
* emit the packed depth/stencil buffer packet.
*/
@@ -580,32 +605,26 @@ static void emit_depthbuffer(struct brw_context *brw)
ADVANCE_BATCH();
} else {
- struct intel_region *region = depth_irb->mt->region;
- uint32_t offset;
+ struct intel_region *region = depth_mt->region;
/* If using separate stencil, hiz must be enabled. */
- assert(!separate_stencil || hiz_region);
+ assert(!separate_stencil || hiz_mt);
assert(intel->gen < 6 || region->tiling == I915_TILING_Y);
- assert(!hiz_region || region->tiling == I915_TILING_Y);
-
- offset = intel_region_get_aligned_offset(region,
- depth_irb->draw_x & ~tile_mask_x,
- depth_irb->draw_y & ~tile_mask_y,
- false);
+ assert(!hiz_mt || region->tiling == I915_TILING_Y);
BEGIN_BATCH(len);
OUT_BATCH(_3DSTATE_DEPTH_BUFFER << 16 | (len - 2));
OUT_BATCH(((region->pitch * region->cpp) - 1) |
(brw_depthbuffer_format(brw) << 18) |
- ((hiz_region ? 1 : 0) << 21) | /* separate stencil enable */
- ((hiz_region ? 1 : 0) << 22) | /* hiz enable */
+ ((hiz_mt ? 1 : 0) << 21) | /* separate stencil enable */
+ ((hiz_mt ? 1 : 0) << 22) | /* hiz enable */
(BRW_TILEWALK_YMAJOR << 26) |
((region->tiling != I915_TILING_NONE) << 27) |
(BRW_SURFACE_2D << 29));
OUT_RELOC(region->bo,
I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
- offset);
+ brw->depthstencil.depth_offset);
OUT_BATCH((BRW_SURFACE_MIPMAPLAYOUT_BELOW << 1) |
(((depth_irb->Base.Base.Width + tile_x) - 1) << 6) |
(((depth_irb->Base.Base.Height + tile_y) - 1) << 19));
@@ -622,7 +641,7 @@ static void emit_depthbuffer(struct brw_context *brw)
ADVANCE_BATCH();
}
- if (hiz_region || separate_stencil) {
+ if (hiz_mt || separate_stencil) {
/*
* In the 3DSTATE_DEPTH_BUFFER batch emitted above, the 'separate
* stencil enable' and 'hiz enable' bits were set. Therefore we must
@@ -632,19 +651,13 @@ static void emit_depthbuffer(struct brw_context *brw)
*/
/* Emit hiz buffer. */
- if (hiz_region) {
- uint32_t hiz_offset =
- intel_region_get_aligned_offset(hiz_region,
- depth_irb->draw_x & ~tile_mask_x,
- (depth_irb->draw_y & ~tile_mask_y) / 2,
- false);
-
+ if (hiz_mt) {
BEGIN_BATCH(3);
OUT_BATCH((_3DSTATE_HIER_DEPTH_BUFFER << 16) | (3 - 2));
- OUT_BATCH(hiz_region->pitch * hiz_region->cpp - 1);
- OUT_RELOC(hiz_region->bo,
+ OUT_BATCH(hiz_mt->region->pitch * hiz_mt->region->cpp - 1);
+ OUT_RELOC(hiz_mt->region->bo,
I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
- hiz_offset);
+ brw->depthstencil.hiz_offset);
ADVANCE_BATCH();
} else {
BEGIN_BATCH(3);
@@ -658,14 +671,6 @@ static void emit_depthbuffer(struct brw_context *brw)
if (separate_stencil) {
struct intel_region *region = stencil_mt->region;
- /* Note: we can't compute the stencil offset using
- * intel_region_get_aligned_offset(), because stencil_region claims
- * that the region is untiled; in fact it's W tiled.
- */
- uint32_t stencil_offset =
- (stencil_irb->draw_y & ~tile_mask_y) * region->pitch +
- (stencil_irb->draw_x & ~tile_mask_x) * 64;
-
BEGIN_BATCH(3);
OUT_BATCH((_3DSTATE_STENCIL_BUFFER << 16) | (3 - 2));
/* The stencil buffer has quirky pitch requirements. From Vol 2a,
@@ -676,7 +681,7 @@ static void emit_depthbuffer(struct brw_context *brw)
OUT_BATCH(2 * region->pitch * region->cpp - 1);
OUT_RELOC(region->bo,
I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
- stencil_offset);
+ brw->depthstencil.stencil_offset);
ADVANCE_BATCH();
} else {
BEGIN_BATCH(3);
@@ -695,7 +700,7 @@ static void emit_depthbuffer(struct brw_context *brw)
* 3DSTATE_CLEAR_PARAMS packet must follow the DEPTH_BUFFER_STATE packet
* when HiZ is enabled and the DEPTH_BUFFER_STATE changes.
*/
- if (intel->gen >= 6 || hiz_region) {
+ if (intel->gen >= 6 || hiz_mt) {
if (intel->gen == 6)
intel_emit_post_sync_nonzero_flush(intel);