aboutsummaryrefslogtreecommitdiffstats
path: root/src/mesa/drivers/dri/i965
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/drivers/dri/i965')
-rw-r--r--src/mesa/drivers/dri/i965/brw_misc_state.c96
-rw-r--r--src/mesa/drivers/dri/i965/gen6_hiz.c54
-rw-r--r--src/mesa/drivers/dri/i965/gen7_hiz.c54
-rw-r--r--src/mesa/drivers/dri/i965/gen7_misc_state.c79
4 files changed, 242 insertions, 41 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_misc_state.c b/src/mesa/drivers/dri/i965/brw_misc_state.c
index 51ea03b6a3f..7a0f5a31ac0 100644
--- a/src/mesa/drivers/dri/i965/brw_misc_state.c
+++ b/src/mesa/drivers/dri/i965/brw_misc_state.c
@@ -266,10 +266,45 @@ static void emit_depthbuffer(struct brw_context *brw)
unsigned int len;
bool separate_stencil = false;
+ /* Amount by which drawing should be offset in order to draw to the
+ * appropriate miplevel/zoffset/cubeface. We will extract these values
+ * from depth_irb or stencil_irb once we determine which is present.
+ */
+ uint32_t draw_x = 0, draw_y = 0;
+
+ /* Masks used to determine how much of the draw_x and draw_y offsets should
+ * be performed using the fine adjustment of "depth coordinate offset X/Y"
+ * (dw5 of 3DSTATE_DEPTH_BUFFER). Any remaining coarse adjustment will be
+ * performed by changing the base addresses of the buffers.
+ *
+ * Since the HiZ, depth, and stencil buffers all use the same "depth
+ * coordinate offset X/Y" values, we need to make sure that the coarse
+ * adjustment will be possible to apply to all three buffers. Since coarse
+ * adjustment can only be applied in multiples of the tile size, we will OR
+ * together the tile masks of all the buffers to determine which offsets to
+ * perform as fine adjustments.
+ */
+ uint32_t tile_mask_x = 0, tile_mask_y = 0;
+
+ if (depth_irb) {
+ intel_region_get_tile_masks(depth_irb->mt->region,
+ &tile_mask_x, &tile_mask_y);
+ }
+
if (depth_irb &&
depth_irb->mt &&
depth_irb->mt->hiz_mt) {
hiz_region = depth_irb->mt->hiz_mt->region;
+
+ uint32_t hiz_tile_mask_x, hiz_tile_mask_y;
+ intel_region_get_tile_masks(hiz_region,
+ &hiz_tile_mask_x, &hiz_tile_mask_y);
+
+ /* Each HiZ row represents 2 rows of pixels */
+ hiz_tile_mask_y = hiz_tile_mask_y << 1 | 1;
+
+ tile_mask_x |= hiz_tile_mask_x;
+ tile_mask_y |= hiz_tile_mask_y;
}
/* 3DSTATE_DEPTH_BUFFER, 3DSTATE_STENCIL_BUFFER are both
@@ -286,8 +321,21 @@ static void emit_depthbuffer(struct brw_context *brw)
if (stencil_mt->stencil_mt)
stencil_mt = stencil_mt->stencil_mt;
- if (stencil_mt->format == MESA_FORMAT_S8)
+ if (stencil_mt->format == MESA_FORMAT_S8) {
separate_stencil = true;
+
+ /* Separate stencil buffer uses 64x64 tiles. */
+ tile_mask_x |= 63;
+ tile_mask_y |= 63;
+ } else {
+ uint32_t stencil_tile_mask_x, stencil_tile_mask_y;
+ intel_region_get_tile_masks(stencil_mt->region,
+ &stencil_tile_mask_x,
+ &stencil_tile_mask_y);
+
+ tile_mask_x |= stencil_tile_mask_x;
+ tile_mask_y |= stencil_tile_mask_y;
+ }
}
/* If there's a packed depth/stencil bound to stencil only, we need to
@@ -321,6 +369,8 @@ static void emit_depthbuffer(struct brw_context *brw)
ADVANCE_BATCH();
} else if (!depth_irb && separate_stencil) {
+ uint32_t tile_x, tile_y;
+
/*
* There exists a separate stencil buffer but no depth buffer.
*
@@ -343,6 +393,11 @@ static void emit_depthbuffer(struct brw_context *brw)
*/
assert(intel->has_separate_stencil);
+ draw_x = stencil_irb->draw_x;
+ draw_y = stencil_irb->draw_y;
+ tile_x = draw_x & tile_mask_x;
+ tile_y = draw_y & tile_mask_y;
+
BEGIN_BATCH(len);
OUT_BATCH(_3DSTATE_DEPTH_BUFFER << 16 | (len - 2));
OUT_BATCH((BRW_DEPTHFORMAT_D32_FLOAT << 18) |
@@ -352,11 +407,15 @@ static void emit_depthbuffer(struct brw_context *brw)
(1 << 27) | /* tiled surface */
(BRW_SURFACE_2D << 29));
OUT_BATCH(0);
- OUT_BATCH(((stencil_irb->Base.Base.Width - 1) << 6) |
- (stencil_irb->Base.Base.Height - 1) << 19);
- OUT_BATCH(0);
+ OUT_BATCH(((stencil_irb->Base.Base.Width + tile_x - 1) << 6) |
+ (stencil_irb->Base.Base.Height + tile_y - 1) << 19);
OUT_BATCH(0);
+ if (intel->is_g4x || intel->gen >= 5)
+ OUT_BATCH(tile_x | (tile_y << 16));
+ else
+ assert(tile_x == 0 && tile_y == 0);
+
if (intel->gen >= 6)
OUT_BATCH(0);
@@ -369,11 +428,18 @@ static void emit_depthbuffer(struct brw_context *brw)
/* If using separate stencil, hiz must be enabled. */
assert(!separate_stencil || hiz_region);
- offset = intel_renderbuffer_tile_offsets(depth_irb, &tile_x, &tile_y);
-
assert(intel->gen < 6 || region->tiling == I915_TILING_Y);
assert(!hiz_region || region->tiling == I915_TILING_Y);
+ draw_x = depth_irb->draw_x;
+ draw_y = depth_irb->draw_y;
+ tile_x = draw_x & tile_mask_x;
+ tile_y = draw_y & tile_mask_y;
+
+ offset = intel_region_get_aligned_offset(region,
+ draw_x & ~tile_mask_x,
+ draw_y & ~tile_mask_y);
+
BEGIN_BATCH(len);
OUT_BATCH(_3DSTATE_DEPTH_BUFFER << 16 | (len - 2));
OUT_BATCH(((region->pitch * region->cpp) - 1) |
@@ -413,12 +479,17 @@ 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,
+ draw_x & ~tile_mask_x,
+ (draw_y & ~tile_mask_y) / 2);
+
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,
I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
- 0);
+ hiz_offset);
ADVANCE_BATCH();
} else {
BEGIN_BATCH(3);
@@ -431,6 +502,15 @@ static void emit_depthbuffer(struct brw_context *brw)
/* Emit stencil buffer. */
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 =
+ (draw_y & ~tile_mask_y) * region->pitch +
+ (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,
@@ -441,7 +521,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,
- 0);
+ stencil_offset);
ADVANCE_BATCH();
} else {
BEGIN_BATCH(3);
diff --git a/src/mesa/drivers/dri/i965/gen6_hiz.c b/src/mesa/drivers/dri/i965/gen6_hiz.c
index 9837b1fc54d..d9b547c3964 100644
--- a/src/mesa/drivers/dri/i965/gen6_hiz.c
+++ b/src/mesa/drivers/dri/i965/gen6_hiz.c
@@ -261,11 +261,42 @@ gen6_hiz_exec(struct intel_context *intel,
{
struct gl_context *ctx = &intel->ctx;
struct brw_context *brw = brw_context(ctx);
+ uint32_t draw_x, draw_y;
+ uint32_t tile_mask_x, tile_mask_y;
assert(op != GEN6_HIZ_OP_DEPTH_CLEAR); /* Not implemented yet. */
assert(mt->hiz_mt != NULL);
intel_miptree_check_level_layer(mt, level, layer);
+ {
+ /* Construct a dummy renderbuffer just to extract tile offsets. */
+ struct intel_renderbuffer rb;
+ rb.mt = mt;
+ rb.mt_level = level;
+ rb.mt_layer = layer;
+ intel_renderbuffer_set_draw_offset(&rb);
+ draw_x = rb.draw_x;
+ draw_y = rb.draw_y;
+ }
+
+ /* Compute masks to determine how much of draw_x and draw_y should be
+ * performed using the fine adjustment of "depth coordinate offset X/Y"
+ * (dw5 of 3DSTATE_DEPTH_BUFFER). See the emit_depthbuffer() function for
+ * details.
+ */
+ {
+ uint32_t depth_mask_x, depth_mask_y, hiz_mask_x, hiz_mask_y;
+ intel_region_get_tile_masks(mt->region, &depth_mask_x, &depth_mask_y);
+ intel_region_get_tile_masks(mt->hiz_mt->region,
+ &hiz_mask_x, &hiz_mask_y);
+
+ /* Each HiZ row represents 2 rows of pixels */
+ hiz_mask_y = hiz_mask_y << 1 | 1;
+
+ tile_mask_x = depth_mask_x | hiz_mask_x;
+ tile_mask_y = depth_mask_y | hiz_mask_y;
+ }
+
gen6_hiz_emit_batch_head(brw);
gen6_hiz_emit_vertices(brw, mt, level, layer);
@@ -450,18 +481,11 @@ gen6_hiz_exec(struct intel_context *intel,
uint32_t width = mt->level[level].width;
uint32_t height = mt->level[level].height;
- uint32_t tile_x;
- uint32_t tile_y;
- uint32_t offset;
- {
- /* Construct a dummy renderbuffer just to extract tile offsets. */
- struct intel_renderbuffer rb;
- rb.mt = mt;
- rb.mt_level = level;
- rb.mt_layer = layer;
- intel_renderbuffer_set_draw_offset(&rb);
- offset = intel_renderbuffer_tile_offsets(&rb, &tile_x, &tile_y);
- }
+ uint32_t tile_x = draw_x & tile_mask_x;
+ uint32_t tile_y = draw_y & tile_mask_y;
+ uint32_t offset = intel_region_get_aligned_offset(mt->region,
+ draw_x & ~tile_mask_x,
+ draw_y & ~tile_mask_y);
uint32_t format;
switch (mt->format) {
@@ -499,13 +523,17 @@ gen6_hiz_exec(struct intel_context *intel,
/* 3DSTATE_HIER_DEPTH_BUFFER */
{
struct intel_region *hiz_region = mt->hiz_mt->region;
+ uint32_t hiz_offset =
+ intel_region_get_aligned_offset(hiz_region,
+ draw_x & ~tile_mask_x,
+ (draw_y & ~tile_mask_y) / 2);
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,
I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
- 0);
+ hiz_offset);
ADVANCE_BATCH();
}
diff --git a/src/mesa/drivers/dri/i965/gen7_hiz.c b/src/mesa/drivers/dri/i965/gen7_hiz.c
index 18c178eb041..4538ec9f203 100644
--- a/src/mesa/drivers/dri/i965/gen7_hiz.c
+++ b/src/mesa/drivers/dri/i965/gen7_hiz.c
@@ -46,6 +46,8 @@ gen7_hiz_exec(struct intel_context *intel,
{
struct gl_context *ctx = &intel->ctx;
struct brw_context *brw = brw_context(ctx);
+ uint32_t draw_x, draw_y;
+ uint32_t tile_mask_x, tile_mask_y;
assert(op != GEN6_HIZ_OP_DEPTH_CLEAR); /* Not implemented yet. */
assert(mt->hiz_mt != NULL);
@@ -59,6 +61,35 @@ gen7_hiz_exec(struct intel_context *intel,
default: assert(0); break;
}
+ {
+ /* Construct a dummy renderbuffer just to extract tile offsets. */
+ struct intel_renderbuffer rb;
+ rb.mt = mt;
+ rb.mt_level = level;
+ rb.mt_layer = layer;
+ intel_renderbuffer_set_draw_offset(&rb);
+ draw_x = rb.draw_x;
+ draw_y = rb.draw_y;
+ }
+
+ /* Compute masks to determine how much of draw_x and draw_y should be
+ * performed using the fine adjustment of "depth coordinate offset X/Y"
+ * (dw5 of 3DSTATE_DEPTH_BUFFER). See the emit_depthbuffer() function for
+ * details.
+ */
+ {
+ uint32_t depth_mask_x, depth_mask_y, hiz_mask_x, hiz_mask_y;
+ intel_region_get_tile_masks(mt->region, &depth_mask_x, &depth_mask_y);
+ intel_region_get_tile_masks(mt->hiz_mt->region,
+ &hiz_mask_x, &hiz_mask_y);
+
+ /* Each HiZ row represents 2 rows of pixels */
+ hiz_mask_y = hiz_mask_y << 1 | 1;
+
+ tile_mask_x = depth_mask_x | hiz_mask_x;
+ tile_mask_y = depth_mask_y | hiz_mask_y;
+ }
+
gen6_hiz_emit_batch_head(brw);
gen6_hiz_emit_vertices(brw, mt, level, layer);
@@ -327,18 +358,11 @@ gen7_hiz_exec(struct intel_context *intel,
uint32_t width = mt->level[level].width;
uint32_t height = mt->level[level].height;
- uint32_t tile_x;
- uint32_t tile_y;
- uint32_t offset;
- {
- /* Construct a dummy renderbuffer just to extract tile offsets. */
- struct intel_renderbuffer rb;
- rb.mt = mt;
- rb.mt_level = level;
- rb.mt_layer = layer;
- intel_renderbuffer_set_draw_offset(&rb);
- offset = intel_renderbuffer_tile_offsets(&rb, &tile_x, &tile_y);
- }
+ uint32_t tile_x = draw_x & tile_mask_x;
+ uint32_t tile_y = draw_y & tile_mask_y;
+ uint32_t offset = intel_region_get_aligned_offset(mt->region,
+ draw_x & ~tile_mask_x,
+ draw_y & ~tile_mask_y);
intel_emit_depth_stall_flushes(intel);
@@ -364,13 +388,17 @@ gen7_hiz_exec(struct intel_context *intel,
/* 3DSTATE_HIER_DEPTH_BUFFER */
{
struct intel_region *hiz_region = mt->hiz_mt->region;
+ uint32_t hiz_offset =
+ intel_region_get_aligned_offset(hiz_region,
+ draw_x & ~tile_mask_x,
+ (draw_y & ~tile_mask_y) / 2);
BEGIN_BATCH(3);
OUT_BATCH((GEN7_3DSTATE_HIER_DEPTH_BUFFER << 16) | (3 - 2));
OUT_BATCH(hiz_region->pitch * hiz_region->cpp - 1);
OUT_RELOC(hiz_region->bo,
I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
- 0);
+ hiz_offset);
ADVANCE_BATCH();
}
diff --git a/src/mesa/drivers/dri/i965/gen7_misc_state.c b/src/mesa/drivers/dri/i965/gen7_misc_state.c
index 3a6144f2838..d9beda8f36e 100644
--- a/src/mesa/drivers/dri/i965/gen7_misc_state.c
+++ b/src/mesa/drivers/dri/i965/gen7_misc_state.c
@@ -42,18 +42,58 @@ static void emit_depthbuffer(struct brw_context *brw)
*stencil_mt = NULL,
*hiz_mt = NULL;
+ /* Amount by which drawing should be offset in order to draw to the
+ * appropriate miplevel/zoffset/cubeface. We will extract these values
+ * from depth_irb or stencil_irb once we determine which is present.
+ */
+ uint32_t draw_x = 0, draw_y = 0;
+
+ /* Masks used to determine how much of the draw_x and draw_y offsets should
+ * be performed using the fine adjustment of "depth coordinate offset X/Y"
+ * (dw5 of 3DSTATE_DEPTH_BUFFER). Any remaining coarse adjustment will be
+ * performed by changing the base addresses of the buffers.
+ *
+ * Since the HiZ, depth, and stencil buffers all use the same "depth
+ * coordinate offset X/Y" values, we need to make sure that the coarse
+ * adjustment will be possible to apply to all three buffers. Since coarse
+ * adjustment can only be applied in multiples of the tile size, we will OR
+ * together the tile masks of all the buffers to determine which offsets to
+ * perform as fine adjustments.
+ */
+ uint32_t tile_mask_x = 0, tile_mask_y = 0;
+
if (drb)
depth_mt = drb->mt;
- if (depth_mt)
+ if (depth_mt) {
hiz_mt = depth_mt->hiz_mt;
+ intel_region_get_tile_masks(depth_mt->region,
+ &tile_mask_x, &tile_mask_y);
+
+ if (hiz_mt) {
+ uint32_t hiz_tile_mask_x, hiz_tile_mask_y;
+ intel_region_get_tile_masks(hiz_mt->region,
+ &hiz_tile_mask_x, &hiz_tile_mask_y);
+
+ /* Each HiZ row represents 2 rows of pixels */
+ hiz_tile_mask_y = hiz_tile_mask_y << 1 | 1;
+
+ tile_mask_x |= hiz_tile_mask_x;
+ tile_mask_y |= hiz_tile_mask_y;
+ }
+ }
+
if (srb) {
stencil_mt = srb->mt;
if (stencil_mt->stencil_mt)
stencil_mt = stencil_mt->stencil_mt;
assert(stencil_mt->format == MESA_FORMAT_S8);
+
+ /* Stencil buffer uses 64x64 tiles. */
+ tile_mask_x |= 63;
+ tile_mask_y |= 63;
}
/* Gen7 doesn't support packed depth/stencil */
@@ -65,6 +105,7 @@ static void emit_depthbuffer(struct brw_context *brw)
if (depth_mt == NULL) {
uint32_t dw1 = BRW_DEPTHFORMAT_D32_FLOAT << 18;
uint32_t dw3 = 0;
+ uint32_t tile_x, tile_y;
if (stencil_mt == NULL) {
dw1 |= (BRW_SURFACE_NULL << 29);
@@ -72,10 +113,15 @@ static void emit_depthbuffer(struct brw_context *brw)
/* _NEW_STENCIL: enable stencil buffer writes */
dw1 |= ((ctx->Stencil.WriteMask != 0) << 27);
+ draw_x = srb->draw_x;
+ draw_y = srb->draw_y;
+ tile_x = draw_x & tile_mask_x;
+ tile_y = draw_y & tile_mask_y;
+
/* 3DSTATE_STENCIL_BUFFER inherits surface type and dimensions. */
dw1 |= (BRW_SURFACE_2D << 29);
- dw3 = ((srb->Base.Base.Width - 1) << 4) |
- ((srb->Base.Base.Height - 1) << 18);
+ dw3 = ((srb->Base.Base.Width + tile_x - 1) << 4) |
+ ((srb->Base.Base.Height + tile_y - 1) << 18);
}
BEGIN_BATCH(7);
@@ -84,14 +130,21 @@ static void emit_depthbuffer(struct brw_context *brw)
OUT_BATCH(0);
OUT_BATCH(dw3);
OUT_BATCH(0);
- OUT_BATCH(0);
+ OUT_BATCH(tile_x | (tile_y << 16));
OUT_BATCH(0);
ADVANCE_BATCH();
} else {
struct intel_region *region = depth_mt->region;
uint32_t tile_x, tile_y, offset;
- offset = intel_renderbuffer_tile_offsets(drb, &tile_x, &tile_y);
+ draw_x = drb->draw_x;
+ draw_y = drb->draw_y;
+ tile_x = draw_x & tile_mask_x;
+ tile_y = draw_y & tile_mask_y;
+
+ offset = intel_region_get_aligned_offset(region,
+ draw_x & ~tile_mask_x,
+ draw_y & ~tile_mask_y);
assert(region->tiling == I915_TILING_Y);
@@ -122,13 +175,17 @@ static void emit_depthbuffer(struct brw_context *brw)
OUT_BATCH(0);
ADVANCE_BATCH();
} else {
+ uint32_t hiz_offset =
+ intel_region_get_aligned_offset(hiz_mt->region,
+ draw_x & ~tile_mask_x,
+ (draw_y & ~tile_mask_y) / 2);
BEGIN_BATCH(3);
OUT_BATCH(GEN7_3DSTATE_HIER_DEPTH_BUFFER << 16 | (3 - 2));
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,
- 0);
+ hiz_offset);
ADVANCE_BATCH();
}
@@ -141,6 +198,14 @@ static void emit_depthbuffer(struct brw_context *brw)
} else {
const int enabled = intel->is_haswell ? HSW_STENCIL_ENABLED : 0;
+ /* Note: We can't compute the stencil offset using
+ * intel_region_get_aligned_offset(), because the stencil region claims
+ * that the region is untiled; in fact it's W tiled.
+ */
+ uint32_t stencil_offset =
+ (draw_y & ~tile_mask_y) * stencil_mt->region->pitch +
+ (draw_x & ~tile_mask_x) * 64;
+
BEGIN_BATCH(3);
OUT_BATCH(GEN7_3DSTATE_STENCIL_BUFFER << 16 | (3 - 2));
/* The stencil buffer has quirky pitch requirements. From the Graphics
@@ -161,7 +226,7 @@ static void emit_depthbuffer(struct brw_context *brw)
(2 * stencil_mt->region->pitch * stencil_mt->region->cpp - 1));
OUT_RELOC(stencil_mt->region->bo,
I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
- 0);
+ stencil_offset);
ADVANCE_BATCH();
}