From 759d51c367bd5be3b935c49c407988190d995a1f Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Tue, 1 Feb 2022 00:12:46 -0800 Subject: [PATCH] blorp: Implement blitter clears via XY_FAST_COLOR_BLT Vulkan transfer queues need this functionality. A lot of the code is pretty similar to what we have for XY_BLOCK_COPY_BLT. Reviewed-by: Ivan Briano Part-of: --- src/intel/blorp/blorp.h | 5 ++ src/intel/blorp/blorp_clear.c | 36 +++++++++++- src/intel/blorp/blorp_genX_exec.h | 91 +++++++++++++++++++++++++++++-- 3 files changed, 126 insertions(+), 6 deletions(-) diff --git a/src/intel/blorp/blorp.h b/src/intel/blorp/blorp.h index f53ed246d01..f8626c8bcc2 100644 --- a/src/intel/blorp/blorp.h +++ b/src/intel/blorp/blorp.h @@ -210,6 +210,11 @@ blorp_clear_supports_compute(struct blorp_context *blorp, uint8_t color_write_disable, bool blend_enabled, enum isl_aux_usage aux_usage); +bool +blorp_clear_supports_blitter(struct blorp_context *blorp, + const struct blorp_surf *surf, + uint8_t color_write_disable, bool blend_enabled); + bool blorp_copy_supports_compute(struct blorp_context *blorp, const struct isl_surf *src_surf, diff --git a/src/intel/blorp/blorp_clear.c b/src/intel/blorp/blorp_clear.c index 4c65ba217ac..0e7185c9427 100644 --- a/src/intel/blorp/blorp_clear.c +++ b/src/intel/blorp/blorp_clear.c @@ -489,6 +489,36 @@ blorp_fast_clear(struct blorp_batch *batch, batch->blorp->exec(batch, ¶ms); } +bool +blorp_clear_supports_blitter(struct blorp_context *blorp, + const struct blorp_surf *surf, + uint8_t color_write_disable, + bool blend_enabled) +{ + const struct intel_device_info *devinfo = blorp->isl_dev->info; + + if (devinfo->ver < 12) + return false; + + if (surf->surf->samples > 1) + return false; + + if (color_write_disable != 0 || blend_enabled) + return false; + + if (!blorp_blitter_supports_aux(devinfo, surf->aux_usage)) + return false; + + const struct isl_format_layout *fmtl = + isl_format_get_layout(surf->surf->format); + + /* We can only support linear mode for 96bpp. */ + if (fmtl->bpb == 96 && surf->surf->tiling != ISL_TILING_LINEAR) + return false; + + return true; +} + bool blorp_clear_supports_compute(struct blorp_context *blorp, uint8_t color_write_disable, bool blend_enabled, @@ -521,9 +551,13 @@ blorp_clear(struct blorp_batch *batch, params.op = BLORP_OP_SLOW_COLOR_CLEAR; const bool compute = batch->flags & BLORP_BATCH_USE_COMPUTE; - if (compute) + if (compute) { assert(blorp_clear_supports_compute(batch->blorp, color_write_disable, false, surf->aux_usage)); + } else if (batch->flags & BLORP_BATCH_USE_BLITTER) { + assert(blorp_clear_supports_blitter(batch->blorp, surf, + color_write_disable, false)); + } /* Manually apply the clear destination swizzle. This way swizzled clears * will work for swizzles which we can't normally use for rendering and it diff --git a/src/intel/blorp/blorp_genX_exec.h b/src/intel/blorp/blorp_genX_exec.h index e85e411859b..20517584969 100644 --- a/src/intel/blorp/blorp_genX_exec.h +++ b/src/intel/blorp/blorp_genX_exec.h @@ -2537,17 +2537,98 @@ blorp_xy_block_copy_blt(struct blorp_batch *batch, #endif } +UNUSED static void +blorp_xy_fast_color_blit(struct blorp_batch *batch, + const struct blorp_params *params) +{ +#if GFX_VER < 12 + unreachable("Blitter is only supported on Gfx12+"); +#else + UNUSED const struct isl_device *isl_dev = batch->blorp->isl_dev; + const struct isl_surf *dst_surf = ¶ms->dst.surf; + const struct isl_format_layout *fmtl = + isl_format_get_layout(params->dst.view.format); + + assert(batch->flags & BLORP_BATCH_USE_BLITTER); + assert(!(batch->flags & BLORP_BATCH_NO_UPDATE_CLEAR_COLOR)); + assert(!(batch->flags & BLORP_BATCH_PREDICATE_ENABLE)); + assert(params->hiz_op == ISL_AUX_OP_NONE); + + assert(params->num_layers == 1); + assert(params->dst.view.levels == 1); + assert(dst_surf->samples == 1); + assert(fmtl->bpb != 96 || dst_surf->tiling == ISL_TILING_LINEAR); + +#if GFX_VERx10 < 125 + assert(params->dst.view.base_array_layer == 0); + assert(params->dst.z_offset == 0); +#endif + + unsigned dst_pitch_unit = dst_surf->tiling == ISL_TILING_LINEAR ? 1 : 4; + +#if GFX_VERx10 >= 125 + struct isl_extent3d dst_align = isl_get_image_alignment(dst_surf); +#endif + + blorp_emit(batch, GENX(XY_FAST_COLOR_BLT), blt) { + blt.ColorDepth = xy_color_depth(fmtl); + + blt.DestinationPitch = (dst_surf->row_pitch_B / dst_pitch_unit) - 1; + blt.DestinationTiling = xy_bcb_tiling(dst_surf); + blt.DestinationX1 = params->x0; + blt.DestinationY1 = params->y0; + blt.DestinationX2 = params->x1; + blt.DestinationY2 = params->y1; + blt.DestinationBaseAddress = params->dst.addr; + blt.DestinationXOffset = params->dst.tile_x_sa; + blt.DestinationYOffset = params->dst.tile_y_sa; + + isl_color_value_pack((union isl_color_value *) + params->wm_inputs.clear_color, + params->dst.view.format, blt.FillColor); + +#if GFX_VERx10 >= 125 + blt.DestinationSurfaceType = xy_bcb_surf_dim(dst_surf); + blt.DestinationSurfaceWidth = dst_surf->logical_level0_px.w - 1; + blt.DestinationSurfaceHeight = dst_surf->logical_level0_px.h - 1; + blt.DestinationSurfaceDepth = xy_bcb_surf_depth(dst_surf) - 1; + blt.DestinationArrayIndex = + params->dst.view.base_array_layer + params->dst.z_offset; + blt.DestinationSurfaceQPitch = isl_get_qpitch(dst_surf) >> 2; + blt.DestinationLOD = params->dst.view.base_level; + blt.DestinationMipTailStartLOD = 15; + blt.DestinationHorizontalAlign = isl_encode_halign(dst_align.width); + blt.DestinationVerticalAlign = isl_encode_valign(dst_align.height); + blt.DestinationDepthStencilResource = false; + blt.DestinationTargetMemory = + params->dst.addr.local_hint ? XY_MEM_LOCAL : XY_MEM_SYSTEM; + + if (params->dst.aux_usage != ISL_AUX_USAGE_NONE) { + blt.DestinationAuxiliarySurfaceMode = xy_aux_mode(¶ms->dst); + blt.DestinationCompressionEnable = true; + blt.DestinationCompressionFormat = + isl_get_render_compression_format(dst_surf->format); + blt.DestinationClearValueEnable = !!params->dst.clear_color_addr.buffer; + blt.DestinationClearAddress = params->dst.clear_color_addr; + } + + /* XeHP needs special MOCS values for the blitter */ + blt.DestinationMOCS = isl_dev->mocs.blitter_dst; +#endif + } +#endif +} + static void blorp_exec_blitter(struct blorp_batch *batch, const struct blorp_params *params) { blorp_measure_start(batch, params); - /* Someday, if we implement clears on the blit enginer, we can - * use params->src.enabled to determine which case we're in. - */ - assert(params->src.enabled); - blorp_xy_block_copy_blt(batch, params); + if (params->src.enabled) + blorp_xy_block_copy_blt(batch, params); + else + blorp_xy_fast_color_blit(batch, params); blorp_measure_end(batch, params); }