X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fdrivers%2Fdri%2Fi965%2Fbrw_tex_layout.c;h=5e70cd26c7ef151d2364d0cfb10e6bf83a42cc75;hb=46c35c61e9c5c1b56fdd9fcd4eb45591dd16d21d;hp=d912862e50bf2a9781bd772ede04f8350bf7028b;hpb=8da15d75442c94adc1bc087fe164a1fa13c3c0f3;p=mesa.git diff --git a/src/mesa/drivers/dri/i965/brw_tex_layout.c b/src/mesa/drivers/dri/i965/brw_tex_layout.c index d912862e50b..5e70cd26c7e 100644 --- a/src/mesa/drivers/dri/i965/brw_tex_layout.c +++ b/src/mesa/drivers/dri/i965/brw_tex_layout.c @@ -1,5 +1,5 @@ /* - * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. + * Copyright 2006 VMware, Inc. * Copyright © 2006 Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining @@ -28,19 +28,20 @@ * * Code to lay out images in a mipmap tree. * - * \author Keith Whitwell - * \author Michel Dänzer + * \author Keith Whitwell + * \author Michel Dänzer */ #include "intel_mipmap_tree.h" #include "brw_context.h" #include "main/macros.h" +#include "main/glformats.h" #define FILE_DEBUG_FLAG DEBUG_MIPTREE static unsigned int intel_horizontal_texture_alignment_unit(struct brw_context *brw, - gl_format format) + struct intel_mipmap_tree *mt) { /** * From the "Alignment Unit Size" section of various specs, namely: @@ -66,27 +67,30 @@ intel_horizontal_texture_alignment_unit(struct brw_context *brw, * On IVB+, non-special cases can be overridden by setting the SURFACE_STATE * "Surface Horizontal Alignment" field to HALIGN_4 or HALIGN_8. */ - if (_mesa_is_format_compressed(format)) { + if (_mesa_is_format_compressed(mt->format)) { /* The hardware alignment requirements for compressed textures * happen to match the block boundaries. */ unsigned int i, j; - _mesa_get_format_block_size(format, &i, &j); + _mesa_get_format_block_size(mt->format, &i, &j); return i; } - if (format == MESA_FORMAT_S8) + if (mt->format == MESA_FORMAT_S_UINT8) return 8; - if (brw->gen >= 7 && format == MESA_FORMAT_Z16) + if (brw->gen >= 7 && mt->format == MESA_FORMAT_Z_UNORM16) return 8; + if (brw->gen == 8 && mt->mcs_mt && mt->num_samples <= 1) + return 16; + return 4; } static unsigned int intel_vertical_texture_alignment_unit(struct brw_context *brw, - gl_format format) + mesa_format format, bool multisampled) { /** * From the "Alignment Unit Size" section of various specs, namely: @@ -105,20 +109,27 @@ intel_vertical_texture_alignment_unit(struct brw_context *brw, * | Depth Buffer | 2 | 2 | 2 | 4 | 4 | * | Separate Stencil Buffer | N/A | N/A | N/A | 4 | 8 | * | Multisampled (4x or 8x) render target | N/A | N/A | N/A | 4 | 4 | - * | All Others | 2 | 2 | 2 | 2 | 2 | + * | All Others | 2 | 2 | 2 | * | * | * +----------------------------------------------------------------------+ * - * On SNB+, non-special cases can be overridden by setting the SURFACE_STATE - * "Surface Vertical Alignment" field to VALIGN_2 or VALIGN_4. - * - * We currently don't support multisampling. + * Where "*" means either VALIGN_2 or VALIGN_4 depending on the setting of + * the SURFACE_STATE "Surface Vertical Alignment" field. */ if (_mesa_is_format_compressed(format)) return 4; - if (format == MESA_FORMAT_S8) + if (format == MESA_FORMAT_S_UINT8) return brw->gen >= 7 ? 8 : 4; + /* Broadwell only supports VALIGN of 4, 8, and 16. The BSpec says 4 + * should always be used, except for stencil buffers, which should be 8. + */ + if (brw->gen >= 8) + return 4; + + if (multisampled) + return 4; + GLenum base_format = _mesa_get_format_base_format(format); if (brw->gen >= 6 && @@ -127,9 +138,58 @@ intel_vertical_texture_alignment_unit(struct brw_context *brw, return 4; } + if (brw->gen == 7) { + /* On Gen7, we prefer a vertical alignment of 4 when possible, because + * that allows Y tiled render targets. + * + * From the Ivy Bridge PRM, Vol4 Part1 2.12.2.1 (SURFACE_STATE for most + * messages), on p64, under the heading "Surface Vertical Alignment": + * + * Value of 1 [VALIGN_4] is not supported for format YCRCB_NORMAL + * (0x182), YCRCB_SWAPUVY (0x183), YCRCB_SWAPUV (0x18f), YCRCB_SWAPY + * (0x190) + * + * VALIGN_4 is not supported for surface format R32G32B32_FLOAT. + */ + if (base_format == GL_YCBCR_MESA || format == MESA_FORMAT_RGB_FLOAT32) + return 2; + + return 4; + } + return 2; } +static void +gen9_miptree_layout_1d(struct intel_mipmap_tree *mt) +{ + unsigned x = 0; + unsigned width = mt->physical_width0; + unsigned depth = mt->physical_depth0; /* number of array layers. */ + + /* When this layout is used the horizontal alignment is fixed at 64 and the + * hardware ignores the value given in the surface state + */ + const unsigned int align_w = 64; + + mt->total_height = mt->physical_height0; + mt->total_width = 0; + + for (unsigned level = mt->first_level; level <= mt->last_level; level++) { + unsigned img_width; + + intel_miptree_set_level_info(mt, level, x, 0, depth); + + img_width = ALIGN(width, align_w); + + mt->total_width = MAX2(mt->total_width, x + img_width); + + x += img_width; + + width = minify(width, 1); + } +} + static void brw_miptree_layout_2d(struct intel_mipmap_tree *mt) { @@ -171,13 +231,17 @@ brw_miptree_layout_2d(struct intel_mipmap_tree *mt) for (unsigned level = mt->first_level; level <= mt->last_level; level++) { unsigned img_height; - intel_miptree_set_level_info(mt, level, x, y, width, - height, depth); + intel_miptree_set_level_info(mt, level, x, y, depth); img_height = ALIGN(height, mt->align_h); if (mt->compressed) img_height /= mt->align_h; + if (mt->array_layout == ALL_SLICES_AT_EACH_LOD) { + /* Compact arrays with separated miplevels */ + img_height *= depth; + } + /* Because the images are packed better, the final offset * might not be the maximal one: */ @@ -193,6 +257,9 @@ brw_miptree_layout_2d(struct intel_mipmap_tree *mt) width = minify(width, 1); height = minify(height, 1); + + if (mt->target == GL_TEXTURE_3D) + depth = minify(depth, 1); } } @@ -208,30 +275,66 @@ align_cube(struct intel_mipmap_tree *mt) mt->total_height += 2; } +static bool +use_linear_1d_layout(struct brw_context *brw, + struct intel_mipmap_tree *mt) +{ + /* On Gen9+ the mipmap levels of a 1D surface are all laid out in a + * horizontal line. This isn't done for depth/stencil buffers however + * because those will be using a tiled layout + */ + if (brw->gen >= 9 && + (mt->target == GL_TEXTURE_1D || + mt->target == GL_TEXTURE_1D_ARRAY)) { + GLenum base_format = _mesa_get_format_base_format(mt->format); + + if (base_format != GL_DEPTH_COMPONENT && + base_format != GL_DEPTH_STENCIL) + return true; + } + + return false; +} + static void brw_miptree_layout_texture_array(struct brw_context *brw, struct intel_mipmap_tree *mt) { - unsigned qpitch = 0; 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_spacing_lod0) - qpitch = h0; + if (mt->array_layout == ALL_SLICES_AT_EACH_LOD) + mt->qpitch = h0; else - qpitch = (h0 + h1 + (brw->gen >= 7 ? 12 : 11) * mt->align_h); - if (mt->compressed) - qpitch /= 4; + mt->qpitch = (h0 + h1 + (brw->gen >= 7 ? 12 : 11) * mt->align_h); + + int physical_qpitch = mt->compressed ? mt->qpitch / 4 : mt->qpitch; - brw_miptree_layout_2d(mt); + if (layout_1d) + gen9_miptree_layout_1d(mt); + else + brw_miptree_layout_2d(mt); for (unsigned level = mt->first_level; level <= mt->last_level; level++) { - for (int q = 0; q < mt->physical_depth0; q++) { - intel_miptree_set_image_offset(mt, level, q, 0, q * qpitch); + unsigned img_height; + img_height = ALIGN(height, mt->align_h); + if (mt->compressed) + img_height /= mt->align_h; + + for (int q = 0; q < mt->level[level].depth; q++) { + if (mt->array_layout == ALL_SLICES_AT_EACH_LOD) { + intel_miptree_set_image_offset(mt, level, q, 0, q * img_height); + } else { + intel_miptree_set_image_offset(mt, level, q, 0, q * physical_qpitch); + } } + height = minify(height, 1); } - mt->total_height = qpitch * mt->physical_depth0; + if (mt->array_layout == ALL_LOD_IN_EACH_SLICE) + mt->total_height = physical_qpitch * mt->physical_depth0; align_cube(mt); } @@ -256,7 +359,7 @@ brw_miptree_layout_texture_3d(struct brw_context *brw, if (mt->target == GL_TEXTURE_CUBE_MAP) DL = 6; - intel_miptree_set_level_info(mt, level, 0, 0, WL, HL, DL); + intel_miptree_set_level_info(mt, level, 0, 0, DL); for (unsigned q = 0; q < DL; q++) { unsigned x = (q % (1 << level)) * wL; @@ -276,8 +379,42 @@ brw_miptree_layout_texture_3d(struct brw_context *brw, void brw_miptree_layout(struct brw_context *brw, struct intel_mipmap_tree *mt) { - mt->align_w = intel_horizontal_texture_alignment_unit(brw, mt->format); - mt->align_h = intel_vertical_texture_alignment_unit(brw, mt->format); + bool multisampled = mt->num_samples > 1; + bool gen6_hiz_or_stencil = false; + + if (brw->gen == 6 && mt->array_layout == ALL_SLICES_AT_EACH_LOD) { + const GLenum base_format = _mesa_get_format_base_format(mt->format); + gen6_hiz_or_stencil = _mesa_is_depth_or_stencil_format(base_format); + } + + if (gen6_hiz_or_stencil) { + /* On gen6, we use ALL_SLICES_AT_EACH_LOD for stencil/hiz because the + * hardware doesn't support multiple mip levels on stencil/hiz. + * + * PRM Vol 2, Part 1, 7.5.3 Hierarchical Depth Buffer: + * "The hierarchical depth buffer does not support the LOD field" + * + * PRM Vol 2, Part 1, 7.5.4.1 Separate Stencil Buffer: + * "The stencil depth buffer does not support the LOD field" + */ + if (mt->format == MESA_FORMAT_S_UINT8) { + /* Stencil uses W tiling, so we force W tiling alignment for the + * ALL_SLICES_AT_EACH_LOD miptree layout. + */ + mt->align_w = 64; + mt->align_h = 64; + } else { + /* Depth uses Y tiling, so we force need Y tiling alignment for the + * ALL_SLICES_AT_EACH_LOD miptree layout. + */ + mt->align_w = 128 / mt->cpp; + mt->align_h = 32; + } + } else { + mt->align_w = intel_horizontal_texture_alignment_unit(brw, mt); + mt->align_h = + intel_vertical_texture_alignment_unit(brw, mt->format, multisampled); + } switch (mt->target) { case GL_TEXTURE_CUBE_MAP: @@ -292,7 +429,10 @@ brw_miptree_layout(struct brw_context *brw, struct intel_mipmap_tree *mt) break; case GL_TEXTURE_3D: - brw_miptree_layout_texture_3d(brw, mt); + if (brw->gen >= 9) + brw_miptree_layout_texture_array(brw, mt); + else + brw_miptree_layout_texture_3d(brw, mt); break; case GL_TEXTURE_1D_ARRAY: @@ -310,7 +450,10 @@ brw_miptree_layout(struct brw_context *brw, struct intel_mipmap_tree *mt) break; case INTEL_MSAA_LAYOUT_NONE: case INTEL_MSAA_LAYOUT_IMS: - brw_miptree_layout_2d(mt); + if (use_linear_1d_layout(brw, mt)) + gen9_miptree_layout_1d(mt); + else + brw_miptree_layout_2d(mt); break; } break;