static void intel_miptree_unmap_raw(struct intel_mipmap_tree *mt);
-static bool
-intel_miptree_supports_mcs(struct brw_context *brw,
- const struct intel_mipmap_tree *mt)
-{
- const struct gen_device_info *devinfo = &brw->screen->devinfo;
-
- /* MCS compression only applies to multisampled miptrees */
- if (mt->surf.samples <= 1)
- return false;
-
- /* Prior to Gen7, all MSAA surfaces used IMS layout. */
- if (devinfo->gen < 7)
- return false;
-
- /* See isl_surf_get_mcs_surf for details. */
- if (mt->surf.samples == 16 && mt->surf.logical_level0_px.width > 8192)
- return false;
-
- /* In Gen7, IMS layout is only used for depth and stencil buffers. */
- switch (_mesa_get_format_base_format(mt->format)) {
- case GL_DEPTH_COMPONENT:
- case GL_STENCIL_INDEX:
- case GL_DEPTH_STENCIL:
- return false;
- default:
- /* From the Ivy Bridge PRM, Vol4 Part1 p77 ("MCS Enable"):
- *
- * This field must be set to 0 for all SINT MSRTs when all RT channels
- * are not written
- *
- * In practice this means that we have to disable MCS for all signed
- * integer MSAA buffers. The alternative, to disable MCS only when one
- * of the render target channels is disabled, is impractical because it
- * would require converting between CMS and UMS MSAA layouts on the fly,
- * which is expensive.
- */
- if (devinfo->gen == 7 && _mesa_get_format_datatype(mt->format) == GL_INT) {
- return false;
- } else {
- return true;
- }
- }
-}
-
-static bool
-intel_tiling_supports_ccs(const struct brw_context *brw,
- enum isl_tiling tiling)
-{
- const struct gen_device_info *devinfo = &brw->screen->devinfo;
-
- /* From the Ivy Bridge PRM, Vol2 Part1 11.7 "MCS Buffer for Render
- * Target(s)", beneath the "Fast Color Clear" bullet (p326):
- *
- * - Support is limited to tiled render targets.
- *
- * Gen9 changes the restriction to Y-tile only.
- */
- if (devinfo->gen >= 9)
- return tiling == ISL_TILING_Y0;
- else if (devinfo->gen >= 7)
- return tiling != ISL_TILING_LINEAR;
- else
- return false;
-}
-
-/**
- * For a single-sampled render target ("non-MSRT"), determine if an MCS buffer
- * can be used. This doesn't (and should not) inspect any of the properties of
- * the miptree's BO.
- *
- * From the Ivy Bridge PRM, Vol2 Part1 11.7 "MCS Buffer for Render Target(s)",
- * beneath the "Fast Color Clear" bullet (p326):
- *
- * - Support is for non-mip-mapped and non-array surface types only.
- *
- * And then later, on p327:
- *
- * - MCS buffer for non-MSRT is supported only for RT formats 32bpp,
- * 64bpp, and 128bpp.
- *
- * From the Skylake documentation, it is made clear that X-tiling is no longer
- * supported:
- *
- * - MCS and Lossless compression is supported for TiledY/TileYs/TileYf
- * non-MSRTs only.
- */
-static bool
-intel_miptree_supports_ccs(struct brw_context *brw,
- const struct intel_mipmap_tree *mt)
-{
- const struct gen_device_info *devinfo = &brw->screen->devinfo;
-
- /* MCS support does not exist prior to Gen7 */
- if (devinfo->gen < 7)
- return false;
-
- /* This function applies only to non-multisampled render targets. */
- if (mt->surf.samples > 1)
- return false;
-
- /* MCS is only supported for color buffers */
- if (!_mesa_is_format_color_format(mt->format))
- return false;
-
- if (mt->cpp != 4 && mt->cpp != 8 && mt->cpp != 16)
- return false;
-
- const bool mip_mapped = mt->first_level != 0 || mt->last_level != 0;
- const bool arrayed = mt->surf.logical_level0_px.array_len > 1 ||
- mt->surf.logical_level0_px.depth > 1;
-
- if (arrayed) {
- /* Multisample surfaces with the CMS layout are not layered surfaces,
- * yet still have physical_depth0 > 1. Assert that we don't
- * accidentally reject a multisampled surface here. We should have
- * rejected it earlier by explicitly checking the sample count.
- */
- assert(mt->surf.samples == 1);
- }
-
- /* Handle the hardware restrictions...
- *
- * All GENs have the following restriction: "MCS buffer for non-MSRT is
- * supported only for RT formats 32bpp, 64bpp, and 128bpp."
- *
- * From the HSW PRM Volume 7: 3D-Media-GPGPU, page 652: (Color Clear of
- * Non-MultiSampler Render Target Restrictions) Support is for
- * non-mip-mapped and non-array surface types only.
- *
- * From the BDW PRM Volume 7: 3D-Media-GPGPU, page 649: (Color Clear of
- * Non-MultiSampler Render Target Restriction). Mip-mapped and arrayed
- * surfaces are supported with MCS buffer layout with these alignments in
- * the RT space: Horizontal Alignment = 256 and Vertical Alignment = 128.
- *
- * From the SKL PRM Volume 7: 3D-Media-GPGPU, page 632: (Color Clear of
- * Non-MultiSampler Render Target Restriction). Mip-mapped and arrayed
- * surfaces are supported with MCS buffer layout with these alignments in
- * the RT space: Horizontal Alignment = 128 and Vertical Alignment = 64.
- */
- if (devinfo->gen < 8 && (mip_mapped || arrayed))
- return false;
-
- /* The PRM doesn't say this explicitly, but fast-clears don't appear to
- * work for 3D textures until gen9 where the layout of 3D textures changes
- * to match 2D array textures.
- */
- if (devinfo->gen <= 8 && mt->surf.dim != ISL_SURF_DIM_2D)
- return false;
-
- /* There's no point in using an MCS buffer if the surface isn't in a
- * renderable format.
- */
- if (!brw->mesa_format_supports_render[mt->format])
- return false;
-
- return true;
-}
-
-static bool
-intel_tiling_supports_hiz(const struct brw_context *brw,
- enum isl_tiling tiling)
-{
- const struct gen_device_info *devinfo = &brw->screen->devinfo;
-
- if (devinfo->gen < 6)
- return false;
-
- return tiling == ISL_TILING_Y0;
-}
-
-static bool
-intel_miptree_supports_hiz(const struct brw_context *brw,
- const struct intel_mipmap_tree *mt)
-{
- if (!brw->has_hiz)
- return false;
-
- switch (mt->format) {
- case MESA_FORMAT_Z_FLOAT32:
- case MESA_FORMAT_Z32_FLOAT_S8X24_UINT:
- case MESA_FORMAT_Z24_UNORM_X8_UINT:
- case MESA_FORMAT_Z24_UNORM_S8_UINT:
- case MESA_FORMAT_Z_UNORM16:
- return true;
- default:
- return false;
- }
-}
-
/**
* Return true if the format that will be used to access the miptree is
* CCS_E-compatible with the miptree's linear/non-sRGB format.
return isl_formats_are_ccs_e_compatible(devinfo, isl_format, access_format);
}
+/* Determine if CCS_E is supported for a given platform and mesa format. */
static bool
-intel_miptree_supports_ccs_e(struct brw_context *brw,
- const struct intel_mipmap_tree *mt)
+format_supports_ccs_e(const struct brw_context *brw, mesa_format format)
{
- const struct gen_device_info *devinfo = &brw->screen->devinfo;
-
- if (devinfo->gen < 9)
- return false;
-
/* For now compression is only enabled for integer formats even though
* there exist supported floating point formats also. This is a heuristic
* decision based on current public benchmarks. In none of the cases these
* Hence these are left to to be enabled in the future when they are known
* to improve things.
*/
- if (_mesa_get_format_datatype(mt->format) == GL_FLOAT)
- return false;
-
- if (!intel_miptree_supports_ccs(brw, mt))
+ if (_mesa_get_format_datatype(format) == GL_FLOAT)
return false;
/* Many window system buffers are sRGB even if they are never rendered as
* sRGB. For those, we want CCS_E for when sRGBEncode is false. When the
* surface is used as sRGB, we fall back to CCS_D.
*/
- mesa_format linear_format = _mesa_get_srgb_format_linear(mt->format);
+ mesa_format linear_format = _mesa_get_srgb_format_linear(format);
enum isl_format isl_format = brw_isl_format_for_mesa_format(linear_format);
return isl_format_supports_ccs_e(&brw->screen->devinfo, isl_format);
}
if (devinfo->must_use_separate_stencil)
return true;
- return brw->has_separate_stencil &&
- intel_miptree_supports_hiz(brw, mt);
+ return brw->has_separate_stencil && brw->has_hiz;
}
/**
{
assert(mt->aux_usage == ISL_AUX_USAGE_NONE);
- if (intel_miptree_supports_mcs(brw, mt)) {
- assert(mt->surf.msaa_layout == ISL_MSAA_LAYOUT_ARRAY);
- mt->aux_usage = ISL_AUX_USAGE_MCS;
- } else if (intel_tiling_supports_ccs(brw, mt->surf.tiling) &&
- intel_miptree_supports_ccs(brw, mt)) {
- if (!unlikely(INTEL_DEBUG & DEBUG_NO_RBC) &&
- intel_miptree_supports_ccs_e(brw, mt)) {
+ if (_mesa_is_format_color_format(mt->format)) {
+ if (mt->surf.samples > 1) {
+ mt->aux_usage = ISL_AUX_USAGE_MCS;
+ } else if (!unlikely(INTEL_DEBUG & DEBUG_NO_RBC) &&
+ format_supports_ccs_e(brw, mt->format)) {
mt->aux_usage = ISL_AUX_USAGE_CCS_E;
- } else {
+ } else if (brw->mesa_format_supports_render[mt->format]) {
mt->aux_usage = ISL_AUX_USAGE_CCS_D;
}
- } else if (intel_tiling_supports_hiz(brw, mt->surf.tiling) &&
- intel_miptree_supports_hiz(brw, mt)) {
+ } else if (isl_surf_usage_is_depth(mt->surf.usage) && brw->has_hiz) {
mt->aux_usage = ISL_AUX_USAGE_HIZ;
}
if (devinfo->gen < 6 && _mesa_is_format_color_format(format))
tiling_flags &= ~ISL_TILING_Y0_BIT;
- mesa_format mt_fmt;
- if (_mesa_is_format_color_format(format)) {
- mt_fmt = intel_lower_compressed_format(brw, format);
- } else {
+ mesa_format mt_fmt = format;
+ if (!_mesa_is_format_color_format(format) && devinfo->gen >= 6) {
/* Fix up the Z miptree format for how we're splitting out separate
* stencil. Gen7 expects there to be no stencil bits in its depth buffer.
*/
- mt_fmt = (devinfo->gen < 6) ? format :
- intel_depth_format_for_depthstencil_format(format);
+ mt_fmt = intel_depth_format_for_depthstencil_format(format);
}
struct intel_mipmap_tree *mt =
if (mt == NULL)
return NULL;
+ if (intel_miptree_needs_fake_etc(brw, mt)) {
+ mesa_format decomp_format = intel_lower_compressed_format(brw, format);
+ mt->shadow_mt = make_surface(brw, target, decomp_format, first_level,
+ last_level, width0, height0, depth0,
+ num_samples, tiling_flags,
+ mt_surf_usage(decomp_format),
+ alloc_flags, 0, NULL);
+
+ if (mt->shadow_mt == NULL) {
+ intel_miptree_release(&mt);
+ return NULL;
+ }
+ }
+
if (needs_separate_stencil(brw, mt, format)) {
mt->stencil_mt =
make_surface(brw, target, MESA_FORMAT_S_UINT8, first_level, last_level,
}
}
- mt->etc_format = (_mesa_is_format_color_format(format) && mt_fmt != format) ?
- format : MESA_FORMAT_NONE;
-
if (!(flags & MIPTREE_CREATE_NO_AUX))
intel_miptree_choose_aux_usage(brw, mt);
*/
if (mt->aux_usage != ISL_AUX_USAGE_CCS_D &&
!intel_miptree_alloc_aux(brw, mt)) {
- intel_miptree_release(&mt);
- return NULL;
+ mt->aux_usage = ISL_AUX_USAGE_NONE;
+ mt->supports_fast_clear = false;
}
return mt;
*/
if (mt->aux_usage != ISL_AUX_USAGE_CCS_D &&
!intel_miptree_alloc_aux(brw, mt)) {
- intel_miptree_release(&mt);
- return NULL;
+ mt->aux_usage = ISL_AUX_USAGE_NONE;
+ mt->supports_fast_clear = false;
}
}
brw_bo_unreference((*mt)->bo);
intel_miptree_release(&(*mt)->stencil_mt);
- intel_miptree_release(&(*mt)->r8stencil_mt);
+ intel_miptree_release(&(*mt)->shadow_mt);
intel_miptree_aux_buffer_free((*mt)->aux_buf);
free_aux_state_map((*mt)->aux_state);
mt_format = MESA_FORMAT_Z24_UNORM_S8_UINT;
if (mt->format == MESA_FORMAT_Z_FLOAT32 && mt->stencil_mt)
mt_format = MESA_FORMAT_Z32_FLOAT_S8X24_UINT;
- if (mt->etc_format != MESA_FORMAT_NONE)
- mt_format = mt->etc_format;
if (_mesa_get_srgb_format_linear(image->TexFormat) !=
_mesa_get_srgb_format_linear(mt_format))
}
/* We should have a valid aux_surf. */
- assert(aux_surf_ok);
+ if (!aux_surf_ok)
+ return false;
/* No work is needed for a zero-sized auxiliary buffer. */
if (aux_surf.size_B == 0)
switch (mt->aux_usage) {
case ISL_AUX_USAGE_NONE:
- if (mt->format == MESA_FORMAT_S_UINT8 && devinfo->gen <= 7)
- mt->r8stencil_needs_update = true;
+ if (mt->format == MESA_FORMAT_S_UINT8 && devinfo->gen <= 7) {
+ mt->shadow_needs_update = true;
+ } else if (intel_miptree_has_etc_shadow(brw, mt)) {
+ mt->shadow_needs_update = true;
+ }
break;
case ISL_AUX_USAGE_MCS:
assert(src->surf.size_B > 0);
- if (!mt->r8stencil_mt) {
+ if (!mt->shadow_mt) {
assert(devinfo->gen > 6); /* Handle MIPTREE_LAYOUT_GEN6_HIZ_STENCIL */
- mt->r8stencil_mt = make_surface(
+ mt->shadow_mt = make_surface(
brw,
src->target,
MESA_FORMAT_R_UINT8,
ISL_TILING_Y0_BIT,
ISL_SURF_USAGE_TEXTURE_BIT,
BO_ALLOC_BUSY, 0, NULL);
- assert(mt->r8stencil_mt);
+ assert(mt->shadow_mt);
}
- if (src->r8stencil_needs_update == false)
+ if (src->shadow_needs_update == false)
return;
- struct intel_mipmap_tree *dst = mt->r8stencil_mt;
+ struct intel_mipmap_tree *dst = mt->shadow_mt;
for (int level = src->first_level; level <= src->last_level; level++) {
const unsigned depth = src->surf.dim == ISL_SURF_DIM_3D ?
}
brw_cache_flush_for_read(brw, dst->bo);
- src->r8stencil_needs_update = false;
+ src->shadow_needs_update = false;
}
static void *
map->unmap = intel_miptree_unmap_s8;
}
-static void
-intel_miptree_unmap_etc(struct brw_context *brw,
- struct intel_mipmap_tree *mt,
- struct intel_miptree_map *map,
- unsigned int level,
- unsigned int slice)
-{
- uint32_t image_x;
- uint32_t image_y;
- intel_miptree_get_image_offset(mt, level, slice, &image_x, &image_y);
-
- image_x += map->x;
- image_y += map->y;
-
- uint8_t *dst = intel_miptree_map_raw(brw, mt, GL_MAP_WRITE_BIT)
- + image_y * mt->surf.row_pitch_B
- + image_x * mt->cpp;
-
- if (mt->etc_format == MESA_FORMAT_ETC1_RGB8)
- _mesa_etc1_unpack_rgba8888(dst, mt->surf.row_pitch_B,
- map->ptr, map->stride,
- map->w, map->h);
- else
- _mesa_unpack_etc2_format(dst, mt->surf.row_pitch_B,
- map->ptr, map->stride,
- map->w, map->h, mt->etc_format, true);
-
- intel_miptree_unmap_raw(mt);
- free(map->buffer);
-}
-
-static void
-intel_miptree_map_etc(struct brw_context *brw,
- struct intel_mipmap_tree *mt,
- struct intel_miptree_map *map,
- unsigned int level,
- unsigned int slice)
-{
- assert(mt->etc_format != MESA_FORMAT_NONE);
- if (mt->etc_format == MESA_FORMAT_ETC1_RGB8) {
- assert(mt->format == MESA_FORMAT_R8G8B8X8_UNORM);
- }
-
- assert(map->mode & GL_MAP_WRITE_BIT);
- assert(map->mode & GL_MAP_INVALIDATE_RANGE_BIT);
-
- intel_miptree_access_raw(brw, mt, level, slice, true);
-
- map->stride = _mesa_format_row_stride(mt->etc_format, map->w);
- map->buffer = malloc(_mesa_format_image_size(mt->etc_format,
- map->w, map->h, 1));
- map->ptr = map->buffer;
- map->unmap = intel_miptree_unmap_etc;
-}
-
/**
* Mapping functions for packed depth/stencil miptrees backed by real separate
* miptrees for depth and stencil.
if (mt->format == MESA_FORMAT_S_UINT8) {
intel_miptree_map_s8(brw, mt, map, level, slice);
- } else if (mt->etc_format != MESA_FORMAT_NONE &&
- !(mode & BRW_MAP_DIRECT_BIT)) {
- intel_miptree_map_etc(brw, mt, map, level, slice);
} else if (mt->stencil_mt && !(mode & BRW_MAP_DIRECT_BIT)) {
intel_miptree_map_depthstencil(brw, mt, map, level, slice);
} else if (use_intel_mipree_map_blit(brw, mt, map)) {
return mt->fast_clear_color;
}
}
+
+static void
+intel_miptree_update_etc_shadow(struct brw_context *brw,
+ struct intel_mipmap_tree *mt,
+ unsigned int level,
+ unsigned int slice,
+ int level_w,
+ int level_h)
+{
+ ptrdiff_t etc_stride, shadow_stride;
+ void *mptr, *sptr;
+ struct intel_mipmap_tree *smt = mt->shadow_mt;
+
+ assert(intel_miptree_has_etc_shadow(brw, mt));
+
+ intel_miptree_map(brw, mt, level, slice, 0, 0, level_w, level_h,
+ GL_MAP_READ_BIT, &mptr, &etc_stride);
+ intel_miptree_map(brw, smt, level, slice, 0, 0, level_w, level_h,
+ GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT,
+ &sptr, &shadow_stride);
+
+ if (mt->format == MESA_FORMAT_ETC1_RGB8) {
+ _mesa_etc1_unpack_rgba8888(sptr, shadow_stride, mptr, etc_stride,
+ level_w, level_h);
+ } else {
+ /* destination and source images must have the same swizzle */
+ bool is_bgra = (smt->format == MESA_FORMAT_B8G8R8A8_SRGB);
+ _mesa_unpack_etc2_format(sptr, shadow_stride, mptr, etc_stride,
+ level_w, level_h, mt->format, is_bgra);
+ }
+
+ intel_miptree_unmap(brw, mt, level, slice);
+ intel_miptree_unmap(brw, smt, level, slice);
+}
+
+void
+intel_miptree_update_etc_shadow_levels(struct brw_context *brw,
+ struct intel_mipmap_tree *mt)
+{
+ struct intel_mipmap_tree *smt;
+ int num_slices;
+
+ assert(mt);
+ assert(mt->surf.size_B > 0);
+ assert(intel_miptree_has_etc_shadow(brw, mt));
+
+ smt = mt->shadow_mt;
+ num_slices = smt->surf.logical_level0_px.array_len;
+
+ for (int level = smt->first_level; level <= smt->last_level; level++) {
+ int level_w = minify(smt->surf.logical_level0_px.width,
+ level - smt->first_level);
+ int level_h = minify(smt->surf.logical_level0_px.height,
+ level - smt->first_level);
+
+ for (unsigned int slice = 0; slice < num_slices; slice++) {
+ intel_miptree_update_etc_shadow(brw, mt, level, slice, level_w,
+ level_h);
+ }
+ }
+
+ mt->shadow_needs_update = false;
+}