summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChia-I Wu <[email protected]>2013-04-30 12:14:29 +0800
committerChia-I Wu <[email protected]>2013-05-01 11:31:15 +0800
commit334abed8286ab80691c563027424b7a7abcb41b5 (patch)
tree0d3391dba94f3f17a1a1855a61f4f332a5396911
parentce188bb252c0d8cab8a2763e8365985df1a0902b (diff)
ilo: support and prefer compact array spacing
There is no reason to waste the memory when the HW can support compact array spacing (ARYSPC_LOD0).
-rw-r--r--src/gallium/drivers/ilo/ilo_gpe_gen6.c3
-rw-r--r--src/gallium/drivers/ilo/ilo_gpe_gen7.c8
-rw-r--r--src/gallium/drivers/ilo/ilo_resource.c77
-rw-r--r--src/gallium/drivers/ilo/ilo_resource.h4
4 files changed, 77 insertions, 15 deletions
diff --git a/src/gallium/drivers/ilo/ilo_gpe_gen6.c b/src/gallium/drivers/ilo/ilo_gpe_gen6.c
index b3efe2a512e..bbab416ca3b 100644
--- a/src/gallium/drivers/ilo/ilo_gpe_gen6.c
+++ b/src/gallium/drivers/ilo/ilo_gpe_gen6.c
@@ -3740,6 +3740,9 @@ gen6_fill_normal_SURFACE_STATE(const struct ilo_dev_info *dev,
break;
}
+ /* non-full array spacing is supported only on GEN7+ */
+ assert(res->array_spacing_full);
+
/*
* Compute the offset to the layer manually.
*
diff --git a/src/gallium/drivers/ilo/ilo_gpe_gen7.c b/src/gallium/drivers/ilo/ilo_gpe_gen7.c
index 613933290a5..44c4a77912c 100644
--- a/src/gallium/drivers/ilo/ilo_gpe_gen7.c
+++ b/src/gallium/drivers/ilo/ilo_gpe_gen7.c
@@ -1455,8 +1455,7 @@ gen7_fill_normal_SURFACE_STATE(const struct ilo_dev_info *dev,
dw[0] = surface_type << BRW_SURFACE_TYPE_SHIFT |
surface_format << BRW_SURFACE_FORMAT_SHIFT |
- ilo_gpe_gen6_translate_winsys_tiling(res->tiling) << 13 |
- GEN7_SURFACE_ARYSPC_FULL;
+ ilo_gpe_gen6_translate_winsys_tiling(res->tiling) << 13;
if (surface_type != BRW_SURFACE_3D && depth > 1)
dw[0] |= GEN7_SURFACE_IS_ARRAY;
@@ -1467,6 +1466,11 @@ gen7_fill_normal_SURFACE_STATE(const struct ilo_dev_info *dev,
if (res->halign_8)
dw[0] |= GEN7_SURFACE_HALIGN_8;
+ if (res->array_spacing_full)
+ dw[0] |= GEN7_SURFACE_ARYSPC_FULL;
+ else
+ dw[0] |= GEN7_SURFACE_ARYSPC_LOD0;
+
if (render_cache_rw)
dw[0] |= BRW_SURFACE_RC_READ_WRITE;
diff --git a/src/gallium/drivers/ilo/ilo_resource.c b/src/gallium/drivers/ilo/ilo_resource.c
index fd6e858a258..a1f414035dc 100644
--- a/src/gallium/drivers/ilo/ilo_resource.c
+++ b/src/gallium/drivers/ilo/ilo_resource.c
@@ -441,6 +441,7 @@ struct layout_tex_info {
bool compressed;
int block_width, block_height;
int align_i, align_j;
+ bool array_spacing_full;
int qpitch;
struct {
@@ -626,10 +627,45 @@ layout_tex_init(const struct ilo_resource *res, struct layout_tex_info *info)
assert(util_is_power_of_two(info->block_width) &&
util_is_power_of_two(info->block_height));
+ if (is->dev.gen >= ILO_GEN(7)) {
+ /*
+ * From the Ivy Bridge PRM, volume 1 part 1, page 111:
+ *
+ * "note that the depth buffer and stencil buffer have an implied
+ * value of ARYSPC_FULL"
+ *
+ * From the Ivy Bridge PRM, volume 4 part 1, page 66:
+ *
+ * "If Multisampled Surface Storage Format is MSFMT_MSS and Number
+ * of Multisamples is not MULTISAMPLECOUNT_1, this field (Surface
+ * Array Spacing) must be set to ARYSPC_LOD0."
+ *
+ * We use ARYSPC_FULL only when needed, and as such, we never use
+ * ARYSPC_FULL for multisampled resources.
+ */
+ info->array_spacing_full = (templ->last_level > 0 ||
+ util_format_is_depth_or_stencil(templ->format));
+ }
+ else {
+ /*
+ * From the Sandy Bridge PRM, volume 1 part 1, page 115:
+ *
+ * "The separate stencil buffer does not support mip mapping, thus
+ * the storage for LODs other than LOD 0 is not needed. The
+ * following QPitch equation applies only to the separate stencil
+ * buffer:
+ *
+ * QPitch = h_0"
+ *
+ * GEN6 does not support compact spacing otherwise.
+ */
+ info->array_spacing_full = (templ->format != PIPE_FORMAT_S8_UINT);
+ }
+
last_level = templ->last_level;
- /* need at least 2 levels to compute qpitch below */
- if (templ->array_size > 1 && last_level == 0 &&
- templ->format != PIPE_FORMAT_S8_UINT)
+
+ /* need at least 2 levels to compute full qpitch */
+ if (last_level == 0 && templ->array_size > 1 && info->array_spacing_full)
last_level++;
/* compute mip level sizes */
@@ -673,10 +709,7 @@ layout_tex_init(const struct ilo_resource *res, struct layout_tex_info *info)
if (templ->array_size > 1) {
const int h0 = align(info->sizes[0].h, info->align_j);
- if (templ->format == PIPE_FORMAT_S8_UINT) {
- info->qpitch = h0;
- }
- else {
+ if (info->array_spacing_full) {
const int h1 = align(info->sizes[1].h, info->align_j);
/*
@@ -696,6 +729,17 @@ layout_tex_init(const struct ilo_resource *res, struct layout_tex_info *info)
* the value calculated in the equation above, for every other
* odd Surface Height starting from 1 i.e. 1,5,9,13"
*
+ * From the Ivy Bridge PRM, volume 1 part 1, page 111-112:
+ *
+ * "If Surface Array Spacing is set to ARYSPC_FULL (note that the
+ * depth buffer and stencil buffer have an implied value of
+ * ARYSPC_FULL):
+ *
+ * QPitch = (h0 + h1 + 12j)
+ * QPitch = (h0 + h1 + 12j) / 4 (compressed)
+ *
+ * (There are many typos or missing words here...)"
+ *
* To access the N-th slice, an offset of (Stride * QPitch * N) is
* added to the base address. The PRM divides QPitch by 4 for
* compressed formats because the block height for those formats are
@@ -710,6 +754,9 @@ layout_tex_init(const struct ilo_resource *res, struct layout_tex_info *info)
templ->height0 % 4 == 1)
info->qpitch += 4;
}
+ else {
+ info->qpitch = h0;
+ }
}
}
@@ -936,8 +983,10 @@ init_texture(struct ilo_resource *res)
res->compressed = info.compressed;
res->block_width = info.block_width;
res->block_height = info.block_height;
+
res->halign_8 = (info.align_i == 8);
res->valign_4 = (info.align_j == 4);
+ res->array_spacing_full = info.array_spacing_full;
switch (res->base.target) {
case PIPE_TEXTURE_1D:
@@ -968,17 +1017,19 @@ init_texture(struct ilo_resource *res)
static void
init_buffer(struct ilo_resource *res)
{
- res->compressed = false;
- res->block_width = 1;
- res->block_height = 1;
- res->halign_8 = false;
- res->valign_4 = false;
-
res->bo_width = res->base.width0;
res->bo_height = 1;
res->bo_cpp = 1;
res->bo_stride = 0;
res->tiling = INTEL_TILING_NONE;
+
+ res->compressed = false;
+ res->block_width = 1;
+ res->block_height = 1;
+
+ res->halign_8 = false;
+ res->valign_4 = false;
+ res->array_spacing_full = false;
}
static struct pipe_resource *
diff --git a/src/gallium/drivers/ilo/ilo_resource.h b/src/gallium/drivers/ilo/ilo_resource.h
index 2d706ce007d..96464724942 100644
--- a/src/gallium/drivers/ilo/ilo_resource.h
+++ b/src/gallium/drivers/ilo/ilo_resource.h
@@ -64,7 +64,11 @@ struct ilo_resource {
bool compressed;
unsigned block_width;
unsigned block_height;
+
+ /* true if the mip level alignments are stricter */
bool halign_8, valign_4;
+ /* true if space is reserved between layers */
+ bool array_spacing_full;
/* 2D offsets into a layer/slice/face */
struct {