diff options
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_tex_layout.c | 62 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i965/intel_mipmap_tree.h | 10 |
2 files changed, 59 insertions, 13 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_tex_layout.c b/src/mesa/drivers/dri/i965/brw_tex_layout.c index 75b409c3483..440ba6c2ca4 100644 --- a/src/mesa/drivers/dri/i965/brw_tex_layout.c +++ b/src/mesa/drivers/dri/i965/brw_tex_layout.c @@ -301,24 +301,66 @@ static void brw_miptree_layout_texture_array(struct brw_context *brw, struct intel_mipmap_tree *mt) { - int h0, h1; unsigned height = mt->physical_height0; bool layout_1d = use_linear_1d_layout(brw, mt); - - h0 = ALIGN(mt->physical_height0, mt->align_h); - h1 = ALIGN(minify(mt->physical_height0, 1), mt->align_h); - if (mt->array_layout == ALL_SLICES_AT_EACH_LOD) - mt->qpitch = h0; - else - mt->qpitch = (h0 + h1 + (brw->gen >= 7 ? 12 : 11) * mt->align_h); - - int physical_qpitch = mt->compressed ? mt->qpitch / 4 : mt->qpitch; + int physical_qpitch; if (layout_1d) gen9_miptree_layout_1d(mt); else brw_miptree_layout_2d(mt); + if (layout_1d) { + physical_qpitch = 1; + /* When using the horizontal layout the qpitch specifies the distance in + * pixels between array slices. The total_width is forced to be a + * multiple of the horizontal alignment in brw_miptree_layout_1d (in + * this case it's always 64). The vertical alignment is ignored. + */ + mt->qpitch = mt->total_width; + } else if (brw->gen >= 9) { + GLenum base_format; + + /* ALL_SLICES_AT_EACH_LOD isn't supported on Gen8+ but this code will + * effectively end up with a packed qpitch anyway whenever + * mt->first_level == mt->last_level. + */ + assert(mt->array_layout != ALL_SLICES_AT_EACH_LOD); + + /* On Gen9 we can pick whatever qpitch we like as long as it's aligned + * to the vertical alignment so we don't need to add any extra rows. + */ + mt->qpitch = mt->total_height; + + /* If the surface might be used as a stencil buffer or HiZ buffer then + * it needs to be a multiple of 8. + */ + base_format = _mesa_get_format_base_format(mt->format); + if (_mesa_is_depth_or_stencil_format(base_format)) + mt->qpitch = ALIGN(mt->qpitch, 8); + + /* 3D textures need to be aligned to the tile height. At this point we + * don't know which tiling will be used so let's just align it to 32 + */ + if (mt->target == GL_TEXTURE_3D) + mt->qpitch = ALIGN(mt->qpitch, 32); + + /* Unlike previous generations the qpitch is now a multiple of the + * compressed block size so physical_qpitch matches mt->qpitch. + */ + physical_qpitch = mt->qpitch; + } else { + int h0 = ALIGN(mt->physical_height0, mt->align_h); + int h1 = ALIGN(minify(mt->physical_height0, 1), mt->align_h); + + if (mt->array_layout == ALL_SLICES_AT_EACH_LOD) + mt->qpitch = h0; + else + mt->qpitch = (h0 + h1 + (brw->gen >= 7 ? 12 : 11) * mt->align_h); + + physical_qpitch = mt->compressed ? mt->qpitch / 4 : mt->qpitch; + } + for (unsigned level = mt->first_level; level <= mt->last_level; level++) { unsigned img_height; img_height = ALIGN(height, mt->align_h); diff --git a/src/mesa/drivers/dri/i965/intel_mipmap_tree.h b/src/mesa/drivers/dri/i965/intel_mipmap_tree.h index 07960592e2b..77b029452b4 100644 --- a/src/mesa/drivers/dri/i965/intel_mipmap_tree.h +++ b/src/mesa/drivers/dri/i965/intel_mipmap_tree.h @@ -403,10 +403,14 @@ struct intel_mipmap_tree enum miptree_array_layout array_layout; /** - * The distance in rows between array slices in an uncompressed surface. + * The distance in between array slices. * - * For compressed surfaces, slices are stored closer together physically; - * the real distance is (qpitch / block height). + * The value is the one that is sent in the surface state. The actual + * meaning depends on certain criteria. Usually it is simply the number of + * uncompressed rows between each slice. However on Gen9+ for compressed + * surfaces it is the number of blocks. For 1D array surfaces that have the + * mipmap tree stored horizontally it is the number of pixels between each + * slice. */ uint32_t qpitch; |