From: Paul Berry Date: Wed, 4 Jul 2012 12:48:25 +0000 (-0700) Subject: i965/msaa: Add an enum to describe MSAA layout. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=1bd4d456cdecf7bea55f4e3dac574af54efad994;p=mesa.git i965/msaa: Add an enum to describe MSAA layout. From the Ivy Bridge PRM, Vol 1 Part 1, p112: There are three types of multisampled surface layouts designated as follows: - IMS Interleaved Multisampled Surface - CMS Compressed Mulitsampled Surface - UMS Uncompressed Multisampled Surface Previously, the i965 driver only used IMS and UMS formats, and distinguished beetween them using the boolean intel_mipmap_tree::msaa_is_interleaved. To facilitate adding support for the CMS format, this patch replaces that boolean (and other booleans derived from it) with an enum INTEL_MSAA_LAYOUT_{IMS,CMS,UMS}. It also updates the terminology used in comments throughout the driver to match the IMS/CMS/UMS terminology used in the PRM. CMS layout is not yet used. The enum has a fourth possible value, INTEL_MSAA_LAYOUT_NONE, which is used for non-multisampled surfaces. Reviewed-by: Chad Versace --- diff --git a/src/mesa/drivers/dri/i965/brw_blorp.cpp b/src/mesa/drivers/dri/i965/brw_blorp.cpp index afb453001d4..9017e4d8cf6 100644 --- a/src/mesa/drivers/dri/i965/brw_blorp.cpp +++ b/src/mesa/drivers/dri/i965/brw_blorp.cpp @@ -61,6 +61,7 @@ brw_blorp_surface_info::set(struct brw_context *brw, this->num_samples = mt->num_samples; this->array_spacing_lod0 = mt->array_spacing_lod0; this->map_stencil_as_y_tiled = false; + this->msaa_layout = mt->msaa_layout; switch (mt->format) { case MESA_FORMAT_S8: diff --git a/src/mesa/drivers/dri/i965/brw_blorp.h b/src/mesa/drivers/dri/i965/brw_blorp.h index cc7e12e1ae7..053eef74071 100644 --- a/src/mesa/drivers/dri/i965/brw_blorp.h +++ b/src/mesa/drivers/dri/i965/brw_blorp.h @@ -97,6 +97,12 @@ void set(struct brw_context *brw, * surface. Should correspond to one of the BRW_SURFACEFORMAT_* enums. */ uint32_t brw_surfaceformat; + + /** + * For MSAA surfaces, MSAA layout that should be used when setting up the + * surface state for this surface. + */ + intel_msaa_layout msaa_layout; }; @@ -192,38 +198,30 @@ struct brw_blorp_blit_prog_key */ unsigned tex_samples; - /* If tex_samples > 0, this boolean indicates whether or not the GPU - * pipeline will be configured to read from it as though it were an - * interleaved MSAA layout. False if tex_samples == 0. + /* MSAA layout that has been configured in the surface state for texturing + * from. */ - bool tex_interleaved; + intel_msaa_layout tex_layout; /* Actual number of samples per pixel in the source image. */ unsigned src_samples; - /* If src_samples > 0, this boolean indicates whether or not the source - * image uses an interleaved MSAA layout. False if src_samples == 0. - */ - bool src_interleaved; + /* Actual MSAA layout used by the source image. */ + intel_msaa_layout src_layout; /* Number of samples per pixel that have been configured in the render * target. */ unsigned rt_samples; - /* If rt_samples > 0, whether or not the GPU pipeline will be configured - * to write to it as though it were an interleaved MSAA layout. False if - * rt_samples == 0. - */ - bool rt_interleaved; + /* MSAA layout that has been configured in the render target. */ + intel_msaa_layout rt_layout; /* Actual number of samples per pixel in the destination image. */ unsigned dst_samples; - /* If dst_samples > 0, whether or not the destination image uses an - * interleaved MSAA layout. False if dst_samples == 0. - */ - bool dst_interleaved; + /* Actual MSAA layout used by the destination image. */ + intel_msaa_layout dst_layout; /* True if the source image is W tiled. If true, the surface state for the * source image must be configured as Y tiled, and tex_samples must be 0. diff --git a/src/mesa/drivers/dri/i965/brw_blorp_blit.cpp b/src/mesa/drivers/dri/i965/brw_blorp_blit.cpp index 0467607f289..ea98a66d81a 100644 --- a/src/mesa/drivers/dri/i965/brw_blorp_blit.cpp +++ b/src/mesa/drivers/dri/i965/brw_blorp_blit.cpp @@ -288,22 +288,22 @@ enum sampler_message_arg * offset = tile(tiling_format, encode_msaa(num_samples, layout, X, Y, S)) * (X, Y, S) = decode_msaa(num_samples, layout, detile(tiling_format, offset)) * - * For a single-sampled surface, or for a multisampled surface that stores - * each sample in a different array slice, encode_msaa() and decode_msaa are - * the identity function: + * For a single-sampled surface, or for a multisampled surface using + * INTEL_MSAA_LAYOUT_UMS, encode_msaa() and decode_msaa are the identity + * function: * - * encode_msaa(1, N/A, X, Y, 0) = (X, Y, 0) - * decode_msaa(1, N/A, X, Y, 0) = (X, Y, 0) - * encode_msaa(n, sliced, X, Y, S) = (X, Y, S) - * decode_msaa(n, sliced, X, Y, S) = (X, Y, S) + * encode_msaa(1, NONE, X, Y, 0) = (X, Y, 0) + * decode_msaa(1, NONE, X, Y, 0) = (X, Y, 0) + * encode_msaa(n, UMS, X, Y, S) = (X, Y, S) + * decode_msaa(n, UMS, X, Y, S) = (X, Y, S) * - * For a 4x interleaved multisampled surface, encode_msaa() embeds the sample - * number into bit 1 of the X and Y coordinates: + * For a 4x multisampled surface using INTEL_MSAA_LAYOUT_IMS, encode_msaa() + * embeds the sample number into bit 1 of the X and Y coordinates: * - * encode_msaa(4, interleaved, X, Y, S) = (X', Y', 0) + * encode_msaa(4, IMS, X, Y, S) = (X', Y', 0) * where X' = (X & ~0b1) << 1 | (S & 0b1) << 1 | (X & 0b1) * Y' = (Y & ~0b1 ) << 1 | (S & 0b10) | (Y & 0b1) - * decode_msaa(4, interleaved, X, Y, 0) = (X', Y', S) + * decode_msaa(4, IMS, X, Y, 0) = (X', Y', S) * where X' = (X & ~0b11) >> 1 | (X & 0b1) * Y' = (Y & ~0b11) >> 1 | (Y & 0b1) * S = (Y & 0b10) | (X & 0b10) >> 1 @@ -419,8 +419,8 @@ private: void alloc_push_const_regs(int base_reg); void compute_frag_coords(); void translate_tiling(bool old_tiled_w, bool new_tiled_w); - void encode_msaa(unsigned num_samples, bool interleaved); - void decode_msaa(unsigned num_samples, bool interleaved); + void encode_msaa(unsigned num_samples, intel_msaa_layout layout); + void decode_msaa(unsigned num_samples, intel_msaa_layout layout); void kill_if_outside_dst_rect(); void translate_dst_to_src(); void single_to_blend(); @@ -529,7 +529,7 @@ brw_blorp_blit_program::compile(struct brw_context *brw, */ assert(!key->src_tiled_w); assert(key->tex_samples == key->src_samples); - assert(key->tex_interleaved == key->src_interleaved); + assert(key->tex_layout == key->src_layout); assert(key->tex_samples > 0); } @@ -540,10 +540,15 @@ brw_blorp_blit_program::compile(struct brw_context *brw, assert(key->rt_samples > 0); } - /* Interleaved only makes sense on MSAA surfaces */ - if (key->tex_interleaved) assert(key->tex_samples > 0); - if (key->src_interleaved) assert(key->src_samples > 0); - if (key->dst_interleaved) assert(key->dst_samples > 0); + /* Make sure layout is consistent with sample count */ + assert((key->tex_layout == INTEL_MSAA_LAYOUT_NONE) == + (key->tex_samples == 0)); + assert((key->rt_layout == INTEL_MSAA_LAYOUT_NONE) == + (key->rt_samples == 0)); + assert((key->src_layout == INTEL_MSAA_LAYOUT_NONE) == + (key->src_samples == 0)); + assert((key->dst_layout == INTEL_MSAA_LAYOUT_NONE) == + (key->dst_samples == 0)); /* Set up prog_data */ memset(&prog_data, 0, sizeof(prog_data)); @@ -571,12 +576,12 @@ brw_blorp_blit_program::compile(struct brw_context *brw, */ if (rt_tiled_w != key->dst_tiled_w || key->rt_samples != key->dst_samples || - key->rt_interleaved != key->dst_interleaved) { - encode_msaa(key->rt_samples, key->rt_interleaved); + key->rt_layout != key->dst_layout) { + encode_msaa(key->rt_samples, key->rt_layout); /* Now (X, Y, S) = detile(rt_tiling, offset) */ translate_tiling(rt_tiled_w, key->dst_tiled_w); /* Now (X, Y, S) = detile(dst_tiling, offset) */ - decode_msaa(key->dst_samples, key->dst_interleaved); + decode_msaa(key->dst_samples, key->dst_layout); } /* Now (X, Y, S) = decode_msaa(dst_samples, detile(dst_tiling, offset)). @@ -626,12 +631,12 @@ brw_blorp_blit_program::compile(struct brw_context *brw, */ if (tex_tiled_w != key->src_tiled_w || key->tex_samples != key->src_samples || - key->tex_interleaved != key->src_interleaved) { - encode_msaa(key->src_samples, key->src_interleaved); + key->tex_layout != key->src_layout) { + encode_msaa(key->src_samples, key->src_layout); /* Now (X, Y, S) = detile(src_tiling, offset) */ translate_tiling(key->src_tiled_w, tex_tiled_w); /* Now (X, Y, S) = detile(tex_tiling, offset) */ - decode_msaa(key->tex_samples, key->tex_interleaved); + decode_msaa(key->tex_samples, key->tex_layout); } /* Now (X, Y, S) = decode_msaa(tex_samples, detile(tex_tiling, offset)). @@ -801,7 +806,7 @@ brw_blorp_blit_program::translate_tiling(bool old_tiled_w, bool new_tiled_w) return; /* In the code that follows, we can safely assume that S = 0, because W - * tiling formats always use interleaved encoding. + * tiling formats always use IMS layout. */ assert(s_is_zero); @@ -887,15 +892,25 @@ brw_blorp_blit_program::translate_tiling(bool old_tiled_w, bool new_tiled_w) * (See brw_blorp_blit_program). */ void -brw_blorp_blit_program::encode_msaa(unsigned num_samples, bool interleaved) +brw_blorp_blit_program::encode_msaa(unsigned num_samples, + intel_msaa_layout layout) { - if (num_samples == 0) { + switch (layout) { + case INTEL_MSAA_LAYOUT_NONE: /* No translation necessary, and S should already be zero. */ assert(s_is_zero); - } else if (!interleaved) { + break; + case INTEL_MSAA_LAYOUT_CMS: + /* We can't compensate for compressed layout since at this point in the + * program we haven't read from the MCS buffer. + */ + assert(!"Bad layout in encode_msaa"); + break; + case INTEL_MSAA_LAYOUT_UMS: /* No translation necessary. */ - } else { - /* encode_msaa(4, interleaved, X, Y, S) = (X', Y', 0) + break; + case INTEL_MSAA_LAYOUT_IMS: + /* encode_msaa(4, IMS, X, Y, S) = (X', Y', 0) * where X' = (X & ~0b1) << 1 | (S & 0b1) << 1 | (X & 0b1) * Y' = (Y & ~0b1 ) << 1 | (S & 0b10) | (Y & 0b1) */ @@ -918,6 +933,7 @@ brw_blorp_blit_program::encode_msaa(unsigned num_samples, bool interleaved) brw_OR(&func, Yp, t1, t2); SWAP_XY_AND_XPYP(); s_is_zero = true; + break; } } @@ -932,15 +948,25 @@ brw_blorp_blit_program::encode_msaa(unsigned num_samples, bool interleaved) * (See brw_blorp_blit_program). */ void -brw_blorp_blit_program::decode_msaa(unsigned num_samples, bool interleaved) +brw_blorp_blit_program::decode_msaa(unsigned num_samples, + intel_msaa_layout layout) { - if (num_samples == 0) { + switch (layout) { + case INTEL_MSAA_LAYOUT_NONE: /* No translation necessary, and S should already be zero. */ assert(s_is_zero); - } else if (!interleaved) { + break; + case INTEL_MSAA_LAYOUT_CMS: + /* We can't compensate for compressed layout since at this point in the + * program we don't have access to the MCS buffer. + */ + assert(!"Bad layout in encode_msaa"); + break; + case INTEL_MSAA_LAYOUT_UMS: /* No translation necessary. */ - } else { - /* decode_msaa(4, interleaved, X, Y, 0) = (X', Y', S) + break; + case INTEL_MSAA_LAYOUT_IMS: + /* decode_msaa(4, IMS, X, Y, 0) = (X', Y', S) * where X' = (X & ~0b11) >> 1 | (X & 0b1) * Y' = (Y & ~0b11) >> 1 | (Y & 0b1) * S = (Y & 0b10) | (X & 0b10) >> 1 @@ -960,6 +986,7 @@ brw_blorp_blit_program::decode_msaa(unsigned num_samples, bool interleaved) brw_OR(&func, S, t1, t2); s_is_zero = false; SWAP_XY_AND_XPYP(); + break; } } @@ -1248,6 +1275,40 @@ brw_blorp_coord_transform_params::setup(GLuint src0, GLuint dst0, GLuint dst1, } +/** + * Determine which MSAA layout the GPU pipeline should be configured for, + * based on the chip generation, the number of samples, and the true layout of + * the image in memory. + */ +inline intel_msaa_layout +compute_msaa_layout_for_pipeline(struct brw_context *brw, unsigned num_samples, + intel_msaa_layout true_layout) +{ + if (num_samples == 0) { + /* When configuring the GPU for non-MSAA, we can still accommodate IMS + * format buffers, by transforming coordinates appropriately. + */ + assert(true_layout == INTEL_MSAA_LAYOUT_NONE || + true_layout == INTEL_MSAA_LAYOUT_IMS); + return INTEL_MSAA_LAYOUT_NONE; + } + + /* Prior to Gen7, all MSAA surfaces use IMS layout. */ + if (brw->intel.gen == 6) { + assert(true_layout == INTEL_MSAA_LAYOUT_IMS); + return INTEL_MSAA_LAYOUT_IMS; + } + + /* Since blorp uses color textures and render targets to do all its work + * (even when blitting stencil and depth data), we always have to configure + * the Gen7 GPU to use UMS or CMS layout on Gen7. + */ + assert(true_layout == INTEL_MSAA_LAYOUT_UMS || + true_layout == INTEL_MSAA_LAYOUT_CMS); + return true_layout; +} + + brw_blorp_blit_params::brw_blorp_blit_params(struct brw_context *brw, struct intel_mipmap_tree *src_mt, struct intel_mipmap_tree *dst_mt, @@ -1263,22 +1324,21 @@ brw_blorp_blit_params::brw_blorp_blit_params(struct brw_context *brw, memset(&wm_prog_key, 0, sizeof(wm_prog_key)); if (brw->intel.gen > 6) { - /* Gen7 only supports interleaved MSAA surfaces for texturing with the + /* Gen7's texturing hardware only supports the IMS layout with the * ld2dms instruction (which blorp doesn't use). So if the source is - * interleaved MSAA, we'll have to map it as a single-sampled texture - * and de-interleave the samples ourselves. + * IMS, we'll have to map it as a single-sampled texture and + * de-interleave the samples ourselves. */ - if (src.num_samples > 0 && src_mt->msaa_is_interleaved) + if (src_mt->msaa_layout == INTEL_MSAA_LAYOUT_IMS) src.num_samples = 0; - /* Similarly, Gen7 only supports interleaved MSAA surfaces for depth and - * stencil render targets. Blorp always maps its destination surface as - * a color render target (even if it's actually a depth or stencil - * buffer). So if the destination is interleaved MSAA, we'll have to - * map it as a single-sampled texture and interleave the samples - * ourselves. + /* Similarly, Gen7's rendering hardware only supports the IMS layout for + * depth and stencil render targets. Blorp always maps its destination + * surface as a color render target (even if it's actually a depth or + * stencil buffer). So if the destination is IMS, we'll have to map it + * as a single-sampled texture and interleave the samples ourselves. */ - if (dst.num_samples > 0 && dst_mt->msaa_is_interleaved) + if (dst_mt->msaa_layout == INTEL_MSAA_LAYOUT_IMS) dst.num_samples = 0; } @@ -1324,21 +1384,19 @@ brw_blorp_blit_params::brw_blorp_blit_params(struct brw_context *brw, wm_prog_key.tex_samples = src.num_samples; wm_prog_key.rt_samples = dst.num_samples; - /* tex_interleaved and rt_interleaved indicate whether or not the GPU - * pipeline will access the source and destination surfaces as though they - * use an interleaved layout. Since blorp uses color textures and render - * targets to do all its work (even when blitting stencil and depth data), - * it will always use sliced layout on Gen7. On Gen6, the MSAA layout is - * always interleaved. + /* tex_layout and rt_layout indicate the MSAA layout the GPU pipeline will + * use to access the source and destination surfaces. */ - wm_prog_key.tex_interleaved = src.num_samples > 0 && brw->intel.gen == 6; - wm_prog_key.rt_interleaved = dst.num_samples > 0 && brw->intel.gen == 6; + wm_prog_key.tex_layout = + compute_msaa_layout_for_pipeline(brw, src.num_samples, src.msaa_layout); + wm_prog_key.rt_layout = + compute_msaa_layout_for_pipeline(brw, dst.num_samples, dst.msaa_layout); - /* src_interleaved and dst_interleaved indicate whether src and dst are - * truly interleaved. + /* src_layout and dst_layout indicate the true MSAA layout used by src and + * dst. */ - wm_prog_key.src_interleaved = src_mt->msaa_is_interleaved; - wm_prog_key.dst_interleaved = dst_mt->msaa_is_interleaved; + wm_prog_key.src_layout = src_mt->msaa_layout; + wm_prog_key.dst_layout = dst_mt->msaa_layout; wm_prog_key.src_tiled_w = src.map_stencil_as_y_tiled; wm_prog_key.dst_tiled_w = dst.map_stencil_as_y_tiled; @@ -1358,11 +1416,11 @@ brw_blorp_blit_params::brw_blorp_blit_params(struct brw_context *brw, * will mean that pixels are scrambled within the multisampling pattern. * TODO: what if this makes the coordinates too large? * - * Note: this only works if the destination surface's MSAA layout is - * interleaved. If it's sliced, then we have no choice but to set up - * the rendering pipeline as multisampled. + * Note: this only works if the destination surface uses the IMS layout. + * If it's UMS, then we have no choice but to set up the rendering + * pipeline as multisampled. */ - assert(dst_mt->msaa_is_interleaved); + assert(dst_mt->msaa_layout == INTEL_MSAA_LAYOUT_IMS); x0 = (x0 * 2) & ~3; y0 = (y0 * 2) & ~3; x1 = ALIGN(x1 * 2, 4); @@ -1378,14 +1436,14 @@ brw_blorp_blit_params::brw_blorp_blit_params(struct brw_context *brw, * size, because the differences between W and Y tiling formats will * mean that pixels are scrambled within the tile. * - * Note: if the destination surface configured as an interleaved MSAA - * surface, then the effective tile size we need to align it to is - * smaller, because each pixel covers a 2x2 or a 4x2 block of samples. + * Note: if the destination surface configured to use IMS layout, then + * the effective tile size we need to align it to is smaller, because + * each pixel covers a 2x2 or a 4x2 block of samples. * * TODO: what if this makes the coordinates too large? */ unsigned x_align = 64, y_align = 64; - if (dst_mt->num_samples > 0 && dst_mt->msaa_is_interleaved) { + if (dst_mt->msaa_layout == INTEL_MSAA_LAYOUT_IMS) { x_align /= (dst_mt->num_samples == 4 ? 2 : 4); y_align /= 2; } diff --git a/src/mesa/drivers/dri/i965/brw_tex_layout.c b/src/mesa/drivers/dri/i965/brw_tex_layout.c index f7421318c21..1a2bedb2268 100644 --- a/src/mesa/drivers/dri/i965/brw_tex_layout.c +++ b/src/mesa/drivers/dri/i965/brw_tex_layout.c @@ -168,10 +168,16 @@ brw_miptree_layout(struct intel_context *intel, struct intel_mipmap_tree *mt) break; default: - if (mt->num_samples > 0 && !mt->msaa_is_interleaved) + switch (mt->msaa_layout) { + case INTEL_MSAA_LAYOUT_UMS: + case INTEL_MSAA_LAYOUT_CMS: brw_miptree_layout_texture_array(intel, mt); - else + break; + case INTEL_MSAA_LAYOUT_NONE: + case INTEL_MSAA_LAYOUT_IMS: i945_miptree_layout_2d(mt); + break; + } break; } DBG("%s: %dx%dx%d\n", __FUNCTION__, diff --git a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c index 04ae6b23289..ddf38e3dd35 100644 --- a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c +++ b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c @@ -1022,7 +1022,7 @@ brw_update_renderbuffer_surface(struct brw_context *brw, width, height, depth, true, 0 /* num_samples */, - false /* msaa_is_interleaved */); + INTEL_MSAA_LAYOUT_NONE); intel_miptree_copy_teximage(intel, intel_image, new_mt); intel_miptree_reference(&irb->mt, intel_image->mt); diff --git a/src/mesa/drivers/dri/i965/gen7_wm_surface_state.c b/src/mesa/drivers/dri/i965/gen7_wm_surface_state.c index 557f36f1be0..52312c9787c 100644 --- a/src/mesa/drivers/dri/i965/gen7_wm_surface_state.c +++ b/src/mesa/drivers/dri/i965/gen7_wm_surface_state.c @@ -398,8 +398,8 @@ gen7_update_renderbuffer_surface(struct brw_context *brw, sizeof(*surf), 32, &brw->wm.surf_offset[unit]); memset(surf, 0, sizeof(*surf)); - /* Render targets can't use MSAA interleaved layout */ - assert(!irb->mt->msaa_is_interleaved); + /* Render targets can't use IMS layout */ + assert(irb->mt->msaa_layout != INTEL_MSAA_LAYOUT_IMS); if (irb->mt->align_h == 4) surf->ss0.vertical_alignment = 1; diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c index 41d337fba16..7c95b7924ca 100644 --- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c +++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c @@ -74,7 +74,7 @@ intel_miptree_create_internal(struct intel_context *intel, GLuint depth0, bool for_region, GLuint num_samples, - bool msaa_is_interleaved) + enum intel_msaa_layout msaa_layout) { struct intel_mipmap_tree *mt = calloc(sizeof(*mt), 1); int compress_byte = 0; @@ -96,13 +96,22 @@ intel_miptree_create_internal(struct intel_context *intel, mt->cpp = compress_byte ? compress_byte : _mesa_get_format_bytes(mt->format); mt->num_samples = num_samples; mt->compressed = compress_byte ? 1 : 0; - mt->msaa_is_interleaved = msaa_is_interleaved; + mt->msaa_layout = msaa_layout; mt->refcount = 1; - /* array_spacing_lod0 is only used for non-interleaved MSAA surfaces. - * TODO: can we use it elsewhere? + /* array_spacing_lod0 is only used for non-IMS MSAA surfaces. TODO: can we + * use it elsewhere? */ - mt->array_spacing_lod0 = num_samples > 0 && !msaa_is_interleaved; + switch (msaa_layout) { + case INTEL_MSAA_LAYOUT_NONE: + case INTEL_MSAA_LAYOUT_IMS: + mt->array_spacing_lod0 = false; + break; + case INTEL_MSAA_LAYOUT_UMS: + case INTEL_MSAA_LAYOUT_CMS: + mt->array_spacing_lod0 = true; + break; + } if (target == GL_TEXTURE_CUBE_MAP) { assert(depth0 == 1); @@ -116,8 +125,9 @@ intel_miptree_create_internal(struct intel_context *intel, (intel->must_use_separate_stencil || (intel->has_separate_stencil && intel->vtbl.is_hiz_depth_format(intel, format)))) { - /* MSAA stencil surfaces are always interleaved. */ - bool msaa_is_interleaved = num_samples > 0; + /* MSAA stencil surfaces always use IMS layout. */ + enum intel_msaa_layout msaa_layout = + num_samples > 0 ? INTEL_MSAA_LAYOUT_IMS : INTEL_MSAA_LAYOUT_NONE; mt->stencil_mt = intel_miptree_create(intel, mt->target, MESA_FORMAT_S8, @@ -128,7 +138,7 @@ intel_miptree_create_internal(struct intel_context *intel, mt->depth0, true, num_samples, - msaa_is_interleaved); + msaa_layout); if (!mt->stencil_mt) { intel_miptree_release(&mt); return NULL; @@ -176,7 +186,7 @@ intel_miptree_create(struct intel_context *intel, GLuint depth0, bool expect_accelerated_upload, GLuint num_samples, - bool msaa_is_interleaved) + enum intel_msaa_layout msaa_layout) { struct intel_mipmap_tree *mt; uint32_t tiling = I915_TILING_NONE; @@ -187,7 +197,7 @@ intel_miptree_create(struct intel_context *intel, (base_format == GL_DEPTH_COMPONENT || base_format == GL_DEPTH_STENCIL_EXT)) tiling = I915_TILING_Y; - else if (num_samples > 0) { + else if (msaa_layout != INTEL_MSAA_LAYOUT_NONE) { /* From p82 of the Sandy Bridge PRM, dw3[1] of SURFACE_STATE ("Tiled * Surface"): * @@ -218,7 +228,7 @@ intel_miptree_create(struct intel_context *intel, mt = intel_miptree_create_internal(intel, target, format, first_level, last_level, width0, height0, depth0, - false, num_samples, msaa_is_interleaved); + false, num_samples, msaa_layout); /* * pitch == 0 || height == 0 indicates the null texture */ @@ -256,7 +266,7 @@ intel_miptree_create_for_region(struct intel_context *intel, 0, 0, region->width, region->height, 1, true, 0 /* num_samples */, - false /* msaa_is_interleaved */); + INTEL_MSAA_LAYOUT_NONE); if (!mt) return mt; @@ -266,27 +276,24 @@ intel_miptree_create_for_region(struct intel_context *intel, } /** - * Determine whether the MSAA surface being created should use an interleaved - * layout or a sliced layout, based on the chip generation and the surface - * type. + * Determine which MSAA layout should be used by the MSAA surface being + * created, based on the chip generation and the surface type. */ -static bool -msaa_format_is_interleaved(struct intel_context *intel, gl_format format) +static enum intel_msaa_layout +compute_msaa_layout(struct intel_context *intel, gl_format format) { - /* Prior to Gen7, all surfaces used interleaved layout. */ + /* Prior to Gen7, all MSAA surfaces used IMS layout. */ if (intel->gen < 7) - return true; + return INTEL_MSAA_LAYOUT_IMS; - /* In Gen7, interleaved layout is only used for depth and stencil - * buffers. - */ + /* In Gen7, IMS layout is only used for depth and stencil buffers. */ switch (_mesa_get_format_base_format(format)) { case GL_DEPTH_COMPONENT: case GL_STENCIL_INDEX: case GL_DEPTH_STENCIL: - return true; + return INTEL_MSAA_LAYOUT_IMS; default: - return false; + return INTEL_MSAA_LAYOUT_UMS; } } @@ -299,12 +306,12 @@ intel_miptree_create_for_renderbuffer(struct intel_context *intel, { struct intel_mipmap_tree *mt; uint32_t depth = 1; - bool msaa_is_interleaved = false; + enum intel_msaa_layout msaa_layout = INTEL_MSAA_LAYOUT_NONE; if (num_samples > 0) { /* Adjust width/height/depth for MSAA */ - msaa_is_interleaved = msaa_format_is_interleaved(intel, format); - if (msaa_is_interleaved) { + msaa_layout = compute_msaa_layout(intel, format); + if (msaa_layout == INTEL_MSAA_LAYOUT_IMS) { /* In the Sandy Bridge PRM, volume 4, part 1, page 31, it says: * * "Any of the other messages (sample*, LOD, load4) used with a @@ -362,7 +369,7 @@ intel_miptree_create_for_renderbuffer(struct intel_context *intel, mt = intel_miptree_create(intel, GL_TEXTURE_2D, format, 0, 0, width, height, depth, true, num_samples, - msaa_is_interleaved); + msaa_layout); return mt; } @@ -636,8 +643,7 @@ intel_miptree_alloc_hiz(struct intel_context *intel, GLuint num_samples) { assert(mt->hiz_mt == NULL); - /* MSAA HiZ surfaces are always interleaved. */ - bool msaa_is_interleaved = num_samples > 0; + /* MSAA HiZ surfaces always use IMS layout. */ mt->hiz_mt = intel_miptree_create(intel, mt->target, MESA_FORMAT_X8_Z24, @@ -648,7 +654,7 @@ intel_miptree_alloc_hiz(struct intel_context *intel, mt->depth0, true, num_samples, - msaa_is_interleaved); + INTEL_MSAA_LAYOUT_IMS); if (!mt->hiz_mt) return false; diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h index 564c6a49f14..38412cd1b7f 100644 --- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h +++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h @@ -138,6 +138,42 @@ struct intel_mipmap_level } *slice; }; +/** + * Enum for keeping track of the different MSAA layouts supported by Gen7. + */ +enum intel_msaa_layout +{ + /** + * Ordinary surface with no MSAA. + */ + INTEL_MSAA_LAYOUT_NONE, + + /** + * Interleaved Multisample Surface. The additional samples are + * accommodated by scaling up the width and the height of the surface so + * that all the samples corresponding to a pixel are located at nearby + * memory locations. + */ + INTEL_MSAA_LAYOUT_IMS, + + /** + * Uncompressed Multisample Surface. The surface is stored as a 2D array, + * with array slice n containing all pixel data for sample n. + */ + INTEL_MSAA_LAYOUT_UMS, + + /** + * Compressed Multisample Surface. The surface is stored as in + * INTEL_MSAA_LAYOUT_UMS, but there is an additional buffer called the MCS + * (Multisample Control Surface) buffer. Each pixel in the MCS buffer + * indicates the mapping from sample number to array slice. This allows + * the common case (where all samples constituting a pixel have the same + * color value) to be stored efficiently by just using a single array + * slice. + */ + INTEL_MSAA_LAYOUT_CMS, +}; + struct intel_mipmap_tree { /* Effectively the key: @@ -182,15 +218,9 @@ struct intel_mipmap_tree bool array_spacing_lod0; /** - * For MSAA buffers, there are two possible layouts: - * - Interleaved, in which the additional samples are accommodated - * by scaling up the width and height of the surface. - * - Sliced, in which the surface is stored as a 2D array, with - * array slice n containing all pixel data for sample n. - * - * This value is true if num_samples > 0 and the format is interleaved. + * MSAA layout used by this buffer. */ - bool msaa_is_interleaved; + enum intel_msaa_layout msaa_layout; /* Derived from the above: */ @@ -263,7 +293,7 @@ struct intel_mipmap_tree *intel_miptree_create(struct intel_context *intel, GLuint depth0, bool expect_accelerated_upload, GLuint num_samples, - bool msaa_is_interleaved); + enum intel_msaa_layout msaa_layout); struct intel_mipmap_tree * intel_miptree_create_for_region(struct intel_context *intel, diff --git a/src/mesa/drivers/dri/intel/intel_tex_image.c b/src/mesa/drivers/dri/intel/intel_tex_image.c index 70fe762a101..a023fef5634 100644 --- a/src/mesa/drivers/dri/intel/intel_tex_image.c +++ b/src/mesa/drivers/dri/intel/intel_tex_image.c @@ -101,7 +101,7 @@ intel_miptree_create_for_teximage(struct intel_context *intel, depth, expect_accelerated_upload, 0 /* num_samples */, - false /* msaa_is_interleaved */); + INTEL_MSAA_LAYOUT_NONE); } /* There are actually quite a few combinations this will work for, diff --git a/src/mesa/drivers/dri/intel/intel_tex_validate.c b/src/mesa/drivers/dri/intel/intel_tex_validate.c index c2d7d67df54..34bbbb83930 100644 --- a/src/mesa/drivers/dri/intel/intel_tex_validate.c +++ b/src/mesa/drivers/dri/intel/intel_tex_validate.c @@ -88,7 +88,7 @@ intel_finalize_mipmap_tree(struct intel_context *intel, GLuint unit) depth, true, 0 /* num_samples */, - false /* msaa_is_interleaved */); + INTEL_MSAA_LAYOUT_NONE); if (!intelObj->mt) return false; }