From: Paul Berry Date: Tue, 4 Sep 2012 14:57:37 +0000 (-0700) Subject: i965/gen6+: Adjust stencil buffer size after computing miptree layout. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=bde833c9d014ad8aebfab0d2285184d7e6d5896d;p=mesa.git i965/gen6+: Adjust stencil buffer size after computing miptree layout. Since Gen6+ stencil buffers use W-tiling (a tiling arrangement which drm and the kernel are not aware of) we need to round up the width and height of a stencil buffer to multiples of the W-tile size (64x64) before allocating a stencil buffer. Previously, we rounded up the size of the base miplevel, and then computed the miptree layout based on the rounded up size. This was incorrect, because it meant that the total size of the miptree would not be properly W-tile aligned, and therefore we would not always allocate enough pages. (Note: even though the GL API doesn't allow creation of mipmapped stencil textures, it does allow mipmapping of a combined depth/stencil texture, and on Gen6+, a combined depth/stencil texture is internally implemented as a pair of separate depth and stencil buffers.) For example, on Sandy Bridge, when allocating a mipmapped stencil texture of size 128x128, we would first round up to the nearest multiple of 64x64 (causing no change to the size), and then compute the miptree layout (whose size worked out to 128x196). Then we would request an allocation of 128*196 bytes (6.125 pages), causing 7 pages to be allocated to the texture. However, the texture needs 8 pages, since each W-tile occupies a page, and it takes 2 W-tiles to cover a width of 128 and 4 W-tiles to cover a height of 196. This patch changes the order of operations so that the miptree layout is computed first and then the total size of the miptree is rounded up to be W-tile aligned. NOTE: This is a candidate for stable release branches. Reviewed-by: Eric Anholt --- diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c index 24cd9e9ad99..dbfddc8ffff 100644 --- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c +++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c @@ -200,6 +200,7 @@ intel_miptree_create(struct intel_context *intel, uint32_t tiling = I915_TILING_NONE; GLenum base_format; bool wraps_etc1 = false; + GLuint total_width, total_height; if (format == MESA_FORMAT_ETC1_RGB8) { format = MESA_FORMAT_RGBX8888_REV; @@ -231,16 +232,6 @@ intel_miptree_create(struct intel_context *intel, tiling = I915_TILING_X; } - if (format == MESA_FORMAT_S8) { - /* The stencil buffer is W tiled. However, we request from the kernel a - * non-tiled buffer because the GTT is incapable of W fencing. So round - * up the width and height to match the size of W tiles (64x64). - */ - tiling = I915_TILING_NONE; - width0 = ALIGN(width0, 64); - height0 = ALIGN(height0, 64); - } - mt = intel_miptree_create_internal(intel, target, format, first_level, last_level, width0, height0, depth0, @@ -253,12 +244,25 @@ intel_miptree_create(struct intel_context *intel, return NULL; } + total_width = mt->total_width; + total_height = mt->total_height; + + if (format == MESA_FORMAT_S8) { + /* The stencil buffer is W tiled. However, we request from the kernel a + * non-tiled buffer because the GTT is incapable of W fencing. So round + * up the width and height to match the size of W tiles (64x64). + */ + tiling = I915_TILING_NONE; + total_width = ALIGN(total_width, 64); + total_height = ALIGN(total_height, 64); + } + mt->wraps_etc1 = wraps_etc1; mt->region = intel_region_alloc(intel->intelScreen, tiling, mt->cpp, - mt->total_width, - mt->total_height, + total_width, + total_height, expect_accelerated_upload); mt->offset = 0;