1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2017 Intel Corporation 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be included 12bf215546Sopenharmony_ci * in all copies or substantial portions of the Software. 13bf215546Sopenharmony_ci * 14bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20bf215546Sopenharmony_ci * DEALINGS IN THE SOFTWARE. 21bf215546Sopenharmony_ci */ 22bf215546Sopenharmony_ci 23bf215546Sopenharmony_ci#include <stdio.h> 24bf215546Sopenharmony_ci#include "pipe/p_defines.h" 25bf215546Sopenharmony_ci#include "pipe/p_state.h" 26bf215546Sopenharmony_ci#include "pipe/p_context.h" 27bf215546Sopenharmony_ci#include "pipe/p_screen.h" 28bf215546Sopenharmony_ci#include "util/format/u_format.h" 29bf215546Sopenharmony_ci#include "util/u_inlines.h" 30bf215546Sopenharmony_ci#include "util/u_surface.h" 31bf215546Sopenharmony_ci#include "util/ralloc.h" 32bf215546Sopenharmony_ci#include "intel/blorp/blorp.h" 33bf215546Sopenharmony_ci#include "iris_context.h" 34bf215546Sopenharmony_ci#include "iris_resource.h" 35bf215546Sopenharmony_ci#include "iris_screen.h" 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_ci/** 38bf215546Sopenharmony_ci * Helper function for handling mirror image blits. 39bf215546Sopenharmony_ci * 40bf215546Sopenharmony_ci * If coord0 > coord1, swap them and return "true" (mirrored). 41bf215546Sopenharmony_ci */ 42bf215546Sopenharmony_cistatic bool 43bf215546Sopenharmony_ciapply_mirror(float *coord0, float *coord1) 44bf215546Sopenharmony_ci{ 45bf215546Sopenharmony_ci if (*coord0 > *coord1) { 46bf215546Sopenharmony_ci float tmp = *coord0; 47bf215546Sopenharmony_ci *coord0 = *coord1; 48bf215546Sopenharmony_ci *coord1 = tmp; 49bf215546Sopenharmony_ci return true; 50bf215546Sopenharmony_ci } 51bf215546Sopenharmony_ci return false; 52bf215546Sopenharmony_ci} 53bf215546Sopenharmony_ci 54bf215546Sopenharmony_ci/** 55bf215546Sopenharmony_ci * Compute the number of pixels to clip for each side of a rect 56bf215546Sopenharmony_ci * 57bf215546Sopenharmony_ci * \param x0 The rect's left coordinate 58bf215546Sopenharmony_ci * \param y0 The rect's bottom coordinate 59bf215546Sopenharmony_ci * \param x1 The rect's right coordinate 60bf215546Sopenharmony_ci * \param y1 The rect's top coordinate 61bf215546Sopenharmony_ci * \param min_x The clipping region's left coordinate 62bf215546Sopenharmony_ci * \param min_y The clipping region's bottom coordinate 63bf215546Sopenharmony_ci * \param max_x The clipping region's right coordinate 64bf215546Sopenharmony_ci * \param max_y The clipping region's top coordinate 65bf215546Sopenharmony_ci * \param clipped_x0 The number of pixels to clip from the left side 66bf215546Sopenharmony_ci * \param clipped_y0 The number of pixels to clip from the bottom side 67bf215546Sopenharmony_ci * \param clipped_x1 The number of pixels to clip from the right side 68bf215546Sopenharmony_ci * \param clipped_y1 The number of pixels to clip from the top side 69bf215546Sopenharmony_ci * 70bf215546Sopenharmony_ci * \return false if we clip everything away, true otherwise 71bf215546Sopenharmony_ci */ 72bf215546Sopenharmony_cistatic inline bool 73bf215546Sopenharmony_cicompute_pixels_clipped(float x0, float y0, float x1, float y1, 74bf215546Sopenharmony_ci float min_x, float min_y, float max_x, float max_y, 75bf215546Sopenharmony_ci float *clipped_x0, float *clipped_y0, 76bf215546Sopenharmony_ci float *clipped_x1, float *clipped_y1) 77bf215546Sopenharmony_ci{ 78bf215546Sopenharmony_ci /* If we are going to clip everything away, stop. */ 79bf215546Sopenharmony_ci if (!(min_x <= max_x && 80bf215546Sopenharmony_ci min_y <= max_y && 81bf215546Sopenharmony_ci x0 <= max_x && 82bf215546Sopenharmony_ci y0 <= max_y && 83bf215546Sopenharmony_ci min_x <= x1 && 84bf215546Sopenharmony_ci min_y <= y1 && 85bf215546Sopenharmony_ci x0 <= x1 && 86bf215546Sopenharmony_ci y0 <= y1)) { 87bf215546Sopenharmony_ci return false; 88bf215546Sopenharmony_ci } 89bf215546Sopenharmony_ci 90bf215546Sopenharmony_ci if (x0 < min_x) 91bf215546Sopenharmony_ci *clipped_x0 = min_x - x0; 92bf215546Sopenharmony_ci else 93bf215546Sopenharmony_ci *clipped_x0 = 0; 94bf215546Sopenharmony_ci if (max_x < x1) 95bf215546Sopenharmony_ci *clipped_x1 = x1 - max_x; 96bf215546Sopenharmony_ci else 97bf215546Sopenharmony_ci *clipped_x1 = 0; 98bf215546Sopenharmony_ci 99bf215546Sopenharmony_ci if (y0 < min_y) 100bf215546Sopenharmony_ci *clipped_y0 = min_y - y0; 101bf215546Sopenharmony_ci else 102bf215546Sopenharmony_ci *clipped_y0 = 0; 103bf215546Sopenharmony_ci if (max_y < y1) 104bf215546Sopenharmony_ci *clipped_y1 = y1 - max_y; 105bf215546Sopenharmony_ci else 106bf215546Sopenharmony_ci *clipped_y1 = 0; 107bf215546Sopenharmony_ci 108bf215546Sopenharmony_ci return true; 109bf215546Sopenharmony_ci} 110bf215546Sopenharmony_ci 111bf215546Sopenharmony_ci/** 112bf215546Sopenharmony_ci * Clips a coordinate (left, right, top or bottom) for the src or dst rect 113bf215546Sopenharmony_ci * (whichever requires the largest clip) and adjusts the coordinate 114bf215546Sopenharmony_ci * for the other rect accordingly. 115bf215546Sopenharmony_ci * 116bf215546Sopenharmony_ci * \param mirror true if mirroring is required 117bf215546Sopenharmony_ci * \param src the source rect coordinate (for example src_x0) 118bf215546Sopenharmony_ci * \param dst0 the dst rect coordinate (for example dst_x0) 119bf215546Sopenharmony_ci * \param dst1 the opposite dst rect coordinate (for example dst_x1) 120bf215546Sopenharmony_ci * \param clipped_dst0 number of pixels to clip from the dst coordinate 121bf215546Sopenharmony_ci * \param clipped_dst1 number of pixels to clip from the opposite dst coordinate 122bf215546Sopenharmony_ci * \param scale the src vs dst scale involved for that coordinate 123bf215546Sopenharmony_ci * \param is_left_or_bottom true if we are clipping the left or bottom sides 124bf215546Sopenharmony_ci * of the rect. 125bf215546Sopenharmony_ci */ 126bf215546Sopenharmony_cistatic void 127bf215546Sopenharmony_ciclip_coordinates(bool mirror, 128bf215546Sopenharmony_ci float *src, float *dst0, float *dst1, 129bf215546Sopenharmony_ci float clipped_dst0, 130bf215546Sopenharmony_ci float clipped_dst1, 131bf215546Sopenharmony_ci float scale, 132bf215546Sopenharmony_ci bool is_left_or_bottom) 133bf215546Sopenharmony_ci{ 134bf215546Sopenharmony_ci /* When clipping we need to add or subtract pixels from the original 135bf215546Sopenharmony_ci * coordinates depending on whether we are acting on the left/bottom 136bf215546Sopenharmony_ci * or right/top sides of the rect respectively. We assume we have to 137bf215546Sopenharmony_ci * add them in the code below, and multiply by -1 when we should 138bf215546Sopenharmony_ci * subtract. 139bf215546Sopenharmony_ci */ 140bf215546Sopenharmony_ci int mult = is_left_or_bottom ? 1 : -1; 141bf215546Sopenharmony_ci 142bf215546Sopenharmony_ci if (!mirror) { 143bf215546Sopenharmony_ci *dst0 += clipped_dst0 * mult; 144bf215546Sopenharmony_ci *src += clipped_dst0 * scale * mult; 145bf215546Sopenharmony_ci } else { 146bf215546Sopenharmony_ci *dst1 -= clipped_dst1 * mult; 147bf215546Sopenharmony_ci *src += clipped_dst1 * scale * mult; 148bf215546Sopenharmony_ci } 149bf215546Sopenharmony_ci} 150bf215546Sopenharmony_ci 151bf215546Sopenharmony_ci/** 152bf215546Sopenharmony_ci * Apply a scissor rectangle to blit coordinates. 153bf215546Sopenharmony_ci * 154bf215546Sopenharmony_ci * Returns true if the blit was entirely scissored away. 155bf215546Sopenharmony_ci */ 156bf215546Sopenharmony_cistatic bool 157bf215546Sopenharmony_ciapply_blit_scissor(const struct pipe_scissor_state *scissor, 158bf215546Sopenharmony_ci float *src_x0, float *src_y0, 159bf215546Sopenharmony_ci float *src_x1, float *src_y1, 160bf215546Sopenharmony_ci float *dst_x0, float *dst_y0, 161bf215546Sopenharmony_ci float *dst_x1, float *dst_y1, 162bf215546Sopenharmony_ci bool mirror_x, bool mirror_y) 163bf215546Sopenharmony_ci{ 164bf215546Sopenharmony_ci float clip_dst_x0, clip_dst_x1, clip_dst_y0, clip_dst_y1; 165bf215546Sopenharmony_ci 166bf215546Sopenharmony_ci /* Compute number of pixels to scissor away. */ 167bf215546Sopenharmony_ci if (!compute_pixels_clipped(*dst_x0, *dst_y0, *dst_x1, *dst_y1, 168bf215546Sopenharmony_ci scissor->minx, scissor->miny, 169bf215546Sopenharmony_ci scissor->maxx, scissor->maxy, 170bf215546Sopenharmony_ci &clip_dst_x0, &clip_dst_y0, 171bf215546Sopenharmony_ci &clip_dst_x1, &clip_dst_y1)) 172bf215546Sopenharmony_ci return true; 173bf215546Sopenharmony_ci 174bf215546Sopenharmony_ci // XXX: comments assume source clipping, which we don't do 175bf215546Sopenharmony_ci 176bf215546Sopenharmony_ci /* When clipping any of the two rects we need to adjust the coordinates 177bf215546Sopenharmony_ci * in the other rect considering the scaling factor involved. To obtain 178bf215546Sopenharmony_ci * the best precision we want to make sure that we only clip once per 179bf215546Sopenharmony_ci * side to avoid accumulating errors due to the scaling adjustment. 180bf215546Sopenharmony_ci * 181bf215546Sopenharmony_ci * For example, if src_x0 and dst_x0 need both to be clipped we want to 182bf215546Sopenharmony_ci * avoid the situation where we clip src_x0 first, then adjust dst_x0 183bf215546Sopenharmony_ci * accordingly but then we realize that the resulting dst_x0 still needs 184bf215546Sopenharmony_ci * to be clipped, so we clip dst_x0 and adjust src_x0 again. Because we are 185bf215546Sopenharmony_ci * applying scaling factors to adjust the coordinates in each clipping 186bf215546Sopenharmony_ci * pass we lose some precision and that can affect the results of the 187bf215546Sopenharmony_ci * blorp blit operation slightly. What we want to do here is detect the 188bf215546Sopenharmony_ci * rect that we should clip first for each side so that when we adjust 189bf215546Sopenharmony_ci * the other rect we ensure the resulting coordinate does not need to be 190bf215546Sopenharmony_ci * clipped again. 191bf215546Sopenharmony_ci * 192bf215546Sopenharmony_ci * The code below implements this by comparing the number of pixels that 193bf215546Sopenharmony_ci * we need to clip for each side of both rects considering the scales 194bf215546Sopenharmony_ci * involved. For example, clip_src_x0 represents the number of pixels 195bf215546Sopenharmony_ci * to be clipped for the src rect's left side, so if clip_src_x0 = 5, 196bf215546Sopenharmony_ci * clip_dst_x0 = 4 and scale_x = 2 it means that we are clipping more 197bf215546Sopenharmony_ci * from the dst rect so we should clip dst_x0 only and adjust src_x0. 198bf215546Sopenharmony_ci * This is because clipping 4 pixels in the dst is equivalent to 199bf215546Sopenharmony_ci * clipping 4 * 2 = 8 > 5 in the src. 200bf215546Sopenharmony_ci */ 201bf215546Sopenharmony_ci 202bf215546Sopenharmony_ci if (*src_x0 == *src_x1 || *src_y0 == *src_y1 203bf215546Sopenharmony_ci || *dst_x0 == *dst_x1 || *dst_y0 == *dst_y1) 204bf215546Sopenharmony_ci return true; 205bf215546Sopenharmony_ci 206bf215546Sopenharmony_ci float scale_x = (float) (*src_x1 - *src_x0) / (*dst_x1 - *dst_x0); 207bf215546Sopenharmony_ci float scale_y = (float) (*src_y1 - *src_y0) / (*dst_y1 - *dst_y0); 208bf215546Sopenharmony_ci 209bf215546Sopenharmony_ci /* Clip left side */ 210bf215546Sopenharmony_ci clip_coordinates(mirror_x, src_x0, dst_x0, dst_x1, 211bf215546Sopenharmony_ci clip_dst_x0, clip_dst_x1, scale_x, true); 212bf215546Sopenharmony_ci 213bf215546Sopenharmony_ci /* Clip right side */ 214bf215546Sopenharmony_ci clip_coordinates(mirror_x, src_x1, dst_x1, dst_x0, 215bf215546Sopenharmony_ci clip_dst_x1, clip_dst_x0, scale_x, false); 216bf215546Sopenharmony_ci 217bf215546Sopenharmony_ci /* Clip bottom side */ 218bf215546Sopenharmony_ci clip_coordinates(mirror_y, src_y0, dst_y0, dst_y1, 219bf215546Sopenharmony_ci clip_dst_y0, clip_dst_y1, scale_y, true); 220bf215546Sopenharmony_ci 221bf215546Sopenharmony_ci /* Clip top side */ 222bf215546Sopenharmony_ci clip_coordinates(mirror_y, src_y1, dst_y1, dst_y0, 223bf215546Sopenharmony_ci clip_dst_y1, clip_dst_y0, scale_y, false); 224bf215546Sopenharmony_ci 225bf215546Sopenharmony_ci /* Check for invalid bounds 226bf215546Sopenharmony_ci * Can't blit for 0-dimensions 227bf215546Sopenharmony_ci */ 228bf215546Sopenharmony_ci return *src_x0 == *src_x1 || *src_y0 == *src_y1 229bf215546Sopenharmony_ci || *dst_x0 == *dst_x1 || *dst_y0 == *dst_y1; 230bf215546Sopenharmony_ci} 231bf215546Sopenharmony_ci 232bf215546Sopenharmony_civoid 233bf215546Sopenharmony_ciiris_blorp_surf_for_resource(struct isl_device *isl_dev, 234bf215546Sopenharmony_ci struct blorp_surf *surf, 235bf215546Sopenharmony_ci struct pipe_resource *p_res, 236bf215546Sopenharmony_ci enum isl_aux_usage aux_usage, 237bf215546Sopenharmony_ci unsigned level, 238bf215546Sopenharmony_ci bool is_dest) 239bf215546Sopenharmony_ci{ 240bf215546Sopenharmony_ci struct iris_resource *res = (void *) p_res; 241bf215546Sopenharmony_ci const struct intel_device_info *devinfo = isl_dev->info; 242bf215546Sopenharmony_ci 243bf215546Sopenharmony_ci *surf = (struct blorp_surf) { 244bf215546Sopenharmony_ci .surf = &res->surf, 245bf215546Sopenharmony_ci .addr = (struct blorp_address) { 246bf215546Sopenharmony_ci .buffer = res->bo, 247bf215546Sopenharmony_ci .offset = res->offset, 248bf215546Sopenharmony_ci .reloc_flags = is_dest ? EXEC_OBJECT_WRITE : 0, 249bf215546Sopenharmony_ci .mocs = iris_mocs(res->bo, isl_dev, 250bf215546Sopenharmony_ci is_dest ? ISL_SURF_USAGE_RENDER_TARGET_BIT 251bf215546Sopenharmony_ci : ISL_SURF_USAGE_TEXTURE_BIT), 252bf215546Sopenharmony_ci .local_hint = iris_bo_likely_local(res->bo), 253bf215546Sopenharmony_ci }, 254bf215546Sopenharmony_ci .aux_usage = aux_usage, 255bf215546Sopenharmony_ci }; 256bf215546Sopenharmony_ci 257bf215546Sopenharmony_ci if (aux_usage != ISL_AUX_USAGE_NONE) { 258bf215546Sopenharmony_ci surf->aux_surf = &res->aux.surf; 259bf215546Sopenharmony_ci surf->aux_addr = (struct blorp_address) { 260bf215546Sopenharmony_ci .buffer = res->aux.bo, 261bf215546Sopenharmony_ci .offset = res->aux.offset, 262bf215546Sopenharmony_ci .reloc_flags = is_dest ? EXEC_OBJECT_WRITE : 0, 263bf215546Sopenharmony_ci .mocs = iris_mocs(res->bo, isl_dev, 0), 264bf215546Sopenharmony_ci .local_hint = devinfo->has_flat_ccs || 265bf215546Sopenharmony_ci iris_bo_likely_local(res->aux.bo), 266bf215546Sopenharmony_ci }; 267bf215546Sopenharmony_ci surf->clear_color = res->aux.clear_color; 268bf215546Sopenharmony_ci surf->clear_color_addr = (struct blorp_address) { 269bf215546Sopenharmony_ci .buffer = res->aux.clear_color_bo, 270bf215546Sopenharmony_ci .offset = res->aux.clear_color_offset, 271bf215546Sopenharmony_ci .reloc_flags = 0, 272bf215546Sopenharmony_ci .mocs = iris_mocs(res->aux.clear_color_bo, isl_dev, 0), 273bf215546Sopenharmony_ci .local_hint = devinfo->has_flat_ccs || 274bf215546Sopenharmony_ci iris_bo_likely_local(res->aux.clear_color_bo), 275bf215546Sopenharmony_ci }; 276bf215546Sopenharmony_ci } 277bf215546Sopenharmony_ci} 278bf215546Sopenharmony_ci 279bf215546Sopenharmony_cistatic bool 280bf215546Sopenharmony_ciis_astc(enum isl_format format) 281bf215546Sopenharmony_ci{ 282bf215546Sopenharmony_ci return format != ISL_FORMAT_UNSUPPORTED && 283bf215546Sopenharmony_ci isl_format_get_layout(format)->txc == ISL_TXC_ASTC; 284bf215546Sopenharmony_ci} 285bf215546Sopenharmony_ci 286bf215546Sopenharmony_cistatic void 287bf215546Sopenharmony_citex_cache_flush_hack(struct iris_batch *batch, 288bf215546Sopenharmony_ci enum isl_format view_format, 289bf215546Sopenharmony_ci enum isl_format surf_format) 290bf215546Sopenharmony_ci{ 291bf215546Sopenharmony_ci const struct intel_device_info *devinfo = &batch->screen->devinfo; 292bf215546Sopenharmony_ci 293bf215546Sopenharmony_ci /* The WaSamplerCacheFlushBetweenRedescribedSurfaceReads workaround says: 294bf215546Sopenharmony_ci * 295bf215546Sopenharmony_ci * "Currently Sampler assumes that a surface would not have two 296bf215546Sopenharmony_ci * different format associate with it. It will not properly cache 297bf215546Sopenharmony_ci * the different views in the MT cache, causing a data corruption." 298bf215546Sopenharmony_ci * 299bf215546Sopenharmony_ci * We may need to handle this for texture views in general someday, but 300bf215546Sopenharmony_ci * for now we handle it here, as it hurts copies and blits particularly 301bf215546Sopenharmony_ci * badly because they ofter reinterpret formats. 302bf215546Sopenharmony_ci * 303bf215546Sopenharmony_ci * If the BO hasn't been referenced yet this batch, we assume that the 304bf215546Sopenharmony_ci * texture cache doesn't contain any relevant data nor need flushing. 305bf215546Sopenharmony_ci * 306bf215546Sopenharmony_ci * Icelake (Gfx11+) claims to fix this issue, but seems to still have 307bf215546Sopenharmony_ci * issues with ASTC formats. 308bf215546Sopenharmony_ci */ 309bf215546Sopenharmony_ci bool need_flush = devinfo->ver >= 11 ? 310bf215546Sopenharmony_ci is_astc(surf_format) != is_astc(view_format) : 311bf215546Sopenharmony_ci view_format != surf_format; 312bf215546Sopenharmony_ci if (!need_flush) 313bf215546Sopenharmony_ci return; 314bf215546Sopenharmony_ci 315bf215546Sopenharmony_ci const char *reason = 316bf215546Sopenharmony_ci "workaround: WaSamplerCacheFlushBetweenRedescribedSurfaceReads"; 317bf215546Sopenharmony_ci 318bf215546Sopenharmony_ci iris_emit_pipe_control_flush(batch, reason, PIPE_CONTROL_CS_STALL); 319bf215546Sopenharmony_ci iris_emit_pipe_control_flush(batch, reason, 320bf215546Sopenharmony_ci PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE); 321bf215546Sopenharmony_ci} 322bf215546Sopenharmony_ci 323bf215546Sopenharmony_cistatic struct iris_resource * 324bf215546Sopenharmony_ciiris_resource_for_aspect(struct pipe_resource *p_res, unsigned pipe_mask) 325bf215546Sopenharmony_ci{ 326bf215546Sopenharmony_ci if (pipe_mask == PIPE_MASK_S) { 327bf215546Sopenharmony_ci struct iris_resource *junk, *s_res; 328bf215546Sopenharmony_ci iris_get_depth_stencil_resources(p_res, &junk, &s_res); 329bf215546Sopenharmony_ci return s_res; 330bf215546Sopenharmony_ci } else { 331bf215546Sopenharmony_ci return (struct iris_resource *)p_res; 332bf215546Sopenharmony_ci } 333bf215546Sopenharmony_ci} 334bf215546Sopenharmony_ci 335bf215546Sopenharmony_cistatic enum pipe_format 336bf215546Sopenharmony_cipipe_format_for_aspect(enum pipe_format format, unsigned pipe_mask) 337bf215546Sopenharmony_ci{ 338bf215546Sopenharmony_ci if (pipe_mask == PIPE_MASK_S) { 339bf215546Sopenharmony_ci return util_format_stencil_only(format); 340bf215546Sopenharmony_ci } else if (pipe_mask == PIPE_MASK_Z) { 341bf215546Sopenharmony_ci return util_format_get_depth_only(format); 342bf215546Sopenharmony_ci } else { 343bf215546Sopenharmony_ci return format; 344bf215546Sopenharmony_ci } 345bf215546Sopenharmony_ci} 346bf215546Sopenharmony_ci 347bf215546Sopenharmony_cistatic bool 348bf215546Sopenharmony_ciclear_color_is_fully_zero(const struct iris_resource *res) 349bf215546Sopenharmony_ci{ 350bf215546Sopenharmony_ci return !res->aux.clear_color_unknown && 351bf215546Sopenharmony_ci res->aux.clear_color.u32[0] == 0 && 352bf215546Sopenharmony_ci res->aux.clear_color.u32[1] == 0 && 353bf215546Sopenharmony_ci res->aux.clear_color.u32[2] == 0 && 354bf215546Sopenharmony_ci res->aux.clear_color.u32[3] == 0; 355bf215546Sopenharmony_ci} 356bf215546Sopenharmony_ci 357bf215546Sopenharmony_ci/** 358bf215546Sopenharmony_ci * The pipe->blit() driver hook. 359bf215546Sopenharmony_ci * 360bf215546Sopenharmony_ci * This performs a blit between two surfaces, which copies data but may 361bf215546Sopenharmony_ci * also perform format conversion, scaling, flipping, and so on. 362bf215546Sopenharmony_ci */ 363bf215546Sopenharmony_cistatic void 364bf215546Sopenharmony_ciiris_blit(struct pipe_context *ctx, const struct pipe_blit_info *info) 365bf215546Sopenharmony_ci{ 366bf215546Sopenharmony_ci struct iris_context *ice = (void *) ctx; 367bf215546Sopenharmony_ci struct iris_screen *screen = (struct iris_screen *)ctx->screen; 368bf215546Sopenharmony_ci const struct intel_device_info *devinfo = &screen->devinfo; 369bf215546Sopenharmony_ci struct iris_batch *batch = &ice->batches[IRIS_BATCH_RENDER]; 370bf215546Sopenharmony_ci enum blorp_batch_flags blorp_flags = iris_blorp_flags_for_batch(batch); 371bf215546Sopenharmony_ci 372bf215546Sopenharmony_ci /* We don't support color masking. */ 373bf215546Sopenharmony_ci assert((info->mask & PIPE_MASK_RGBA) == PIPE_MASK_RGBA || 374bf215546Sopenharmony_ci (info->mask & PIPE_MASK_RGBA) == 0); 375bf215546Sopenharmony_ci 376bf215546Sopenharmony_ci if (info->render_condition_enable) { 377bf215546Sopenharmony_ci if (ice->state.predicate == IRIS_PREDICATE_STATE_DONT_RENDER) 378bf215546Sopenharmony_ci return; 379bf215546Sopenharmony_ci 380bf215546Sopenharmony_ci if (ice->state.predicate == IRIS_PREDICATE_STATE_USE_BIT) 381bf215546Sopenharmony_ci blorp_flags |= BLORP_BATCH_PREDICATE_ENABLE; 382bf215546Sopenharmony_ci } 383bf215546Sopenharmony_ci 384bf215546Sopenharmony_ci float src_x0 = info->src.box.x; 385bf215546Sopenharmony_ci float src_x1 = info->src.box.x + info->src.box.width; 386bf215546Sopenharmony_ci float src_y0 = info->src.box.y; 387bf215546Sopenharmony_ci float src_y1 = info->src.box.y + info->src.box.height; 388bf215546Sopenharmony_ci float dst_x0 = info->dst.box.x; 389bf215546Sopenharmony_ci float dst_x1 = info->dst.box.x + info->dst.box.width; 390bf215546Sopenharmony_ci float dst_y0 = info->dst.box.y; 391bf215546Sopenharmony_ci float dst_y1 = info->dst.box.y + info->dst.box.height; 392bf215546Sopenharmony_ci bool mirror_x = apply_mirror(&src_x0, &src_x1); 393bf215546Sopenharmony_ci bool mirror_y = apply_mirror(&src_y0, &src_y1); 394bf215546Sopenharmony_ci enum blorp_filter filter; 395bf215546Sopenharmony_ci 396bf215546Sopenharmony_ci if (info->scissor_enable) { 397bf215546Sopenharmony_ci bool noop = apply_blit_scissor(&info->scissor, 398bf215546Sopenharmony_ci &src_x0, &src_y0, &src_x1, &src_y1, 399bf215546Sopenharmony_ci &dst_x0, &dst_y0, &dst_x1, &dst_y1, 400bf215546Sopenharmony_ci mirror_x, mirror_y); 401bf215546Sopenharmony_ci if (noop) 402bf215546Sopenharmony_ci return; 403bf215546Sopenharmony_ci } 404bf215546Sopenharmony_ci 405bf215546Sopenharmony_ci /* Do DRI PRIME blits on the hardware blitter on Gfx12+ */ 406bf215546Sopenharmony_ci if (devinfo->ver >= 12 && 407bf215546Sopenharmony_ci (info->dst.resource->bind & PIPE_BIND_PRIME_BLIT_DST)) { 408bf215546Sopenharmony_ci assert(!info->render_condition_enable); 409bf215546Sopenharmony_ci assert(util_can_blit_via_copy_region(info, false, false)); 410bf215546Sopenharmony_ci iris_copy_region(&ice->blorp, &ice->batches[IRIS_BATCH_BLITTER], 411bf215546Sopenharmony_ci info->dst.resource, info->dst.level, 412bf215546Sopenharmony_ci info->dst.box.x, info->dst.box.y, info->dst.box.z, 413bf215546Sopenharmony_ci info->src.resource, info->src.level, 414bf215546Sopenharmony_ci &info->src.box); 415bf215546Sopenharmony_ci return; 416bf215546Sopenharmony_ci } 417bf215546Sopenharmony_ci 418bf215546Sopenharmony_ci if (abs(info->dst.box.width) == abs(info->src.box.width) && 419bf215546Sopenharmony_ci abs(info->dst.box.height) == abs(info->src.box.height)) { 420bf215546Sopenharmony_ci if (info->src.resource->nr_samples > 1 && 421bf215546Sopenharmony_ci info->dst.resource->nr_samples <= 1) { 422bf215546Sopenharmony_ci /* The OpenGL ES 3.2 specification, section 16.2.1, says: 423bf215546Sopenharmony_ci * 424bf215546Sopenharmony_ci * "If the read framebuffer is multisampled (its effective 425bf215546Sopenharmony_ci * value of SAMPLE_BUFFERS is one) and the draw framebuffer 426bf215546Sopenharmony_ci * is not (its value of SAMPLE_BUFFERS is zero), the samples 427bf215546Sopenharmony_ci * corresponding to each pixel location in the source are 428bf215546Sopenharmony_ci * converted to a single sample before being written to the 429bf215546Sopenharmony_ci * destination. The filter parameter is ignored. If the 430bf215546Sopenharmony_ci * source formats are integer types or stencil values, a 431bf215546Sopenharmony_ci * single sample’s value is selected for each pixel. If the 432bf215546Sopenharmony_ci * source formats are floating-point or normalized types, 433bf215546Sopenharmony_ci * the sample values for each pixel are resolved in an 434bf215546Sopenharmony_ci * implementation-dependent manner. If the source formats 435bf215546Sopenharmony_ci * are depth values, sample values are resolved in an 436bf215546Sopenharmony_ci * implementation-dependent manner where the result will be 437bf215546Sopenharmony_ci * between the minimum and maximum depth values in the pixel." 438bf215546Sopenharmony_ci * 439bf215546Sopenharmony_ci * When selecting a single sample, we always choose sample 0. 440bf215546Sopenharmony_ci */ 441bf215546Sopenharmony_ci if (util_format_is_depth_or_stencil(info->src.format) || 442bf215546Sopenharmony_ci util_format_is_pure_integer(info->src.format)) { 443bf215546Sopenharmony_ci filter = BLORP_FILTER_SAMPLE_0; 444bf215546Sopenharmony_ci } else { 445bf215546Sopenharmony_ci filter = BLORP_FILTER_AVERAGE; 446bf215546Sopenharmony_ci } 447bf215546Sopenharmony_ci } else { 448bf215546Sopenharmony_ci /* The OpenGL 4.6 specification, section 18.3.1, says: 449bf215546Sopenharmony_ci * 450bf215546Sopenharmony_ci * "If the source and destination dimensions are identical, 451bf215546Sopenharmony_ci * no filtering is applied." 452bf215546Sopenharmony_ci * 453bf215546Sopenharmony_ci * Using BLORP_FILTER_NONE will also handle the upsample case by 454bf215546Sopenharmony_ci * replicating the one value in the source to all values in the 455bf215546Sopenharmony_ci * destination. 456bf215546Sopenharmony_ci */ 457bf215546Sopenharmony_ci filter = BLORP_FILTER_NONE; 458bf215546Sopenharmony_ci } 459bf215546Sopenharmony_ci } else if (info->filter == PIPE_TEX_FILTER_LINEAR) { 460bf215546Sopenharmony_ci filter = BLORP_FILTER_BILINEAR; 461bf215546Sopenharmony_ci } else { 462bf215546Sopenharmony_ci filter = BLORP_FILTER_NEAREST; 463bf215546Sopenharmony_ci } 464bf215546Sopenharmony_ci 465bf215546Sopenharmony_ci struct blorp_batch blorp_batch; 466bf215546Sopenharmony_ci blorp_batch_init(&ice->blorp, &blorp_batch, batch, blorp_flags); 467bf215546Sopenharmony_ci 468bf215546Sopenharmony_ci float src_z_step = (float)info->src.box.depth / (float)info->dst.box.depth; 469bf215546Sopenharmony_ci 470bf215546Sopenharmony_ci /* There is no interpolation to the pixel center during rendering, so 471bf215546Sopenharmony_ci * add the 0.5 offset ourselves here. 472bf215546Sopenharmony_ci */ 473bf215546Sopenharmony_ci float depth_center_offset = 0; 474bf215546Sopenharmony_ci if (info->src.resource->target == PIPE_TEXTURE_3D) 475bf215546Sopenharmony_ci depth_center_offset = 0.5 / info->dst.box.depth * info->src.box.depth; 476bf215546Sopenharmony_ci 477bf215546Sopenharmony_ci /* Perform a blit for each aspect requested by the caller. PIPE_MASK_R is 478bf215546Sopenharmony_ci * used to represent the color aspect. */ 479bf215546Sopenharmony_ci unsigned aspect_mask = info->mask & (PIPE_MASK_R | PIPE_MASK_ZS); 480bf215546Sopenharmony_ci while (aspect_mask) { 481bf215546Sopenharmony_ci unsigned aspect = 1 << u_bit_scan(&aspect_mask); 482bf215546Sopenharmony_ci 483bf215546Sopenharmony_ci struct iris_resource *src_res = 484bf215546Sopenharmony_ci iris_resource_for_aspect(info->src.resource, aspect); 485bf215546Sopenharmony_ci struct iris_resource *dst_res = 486bf215546Sopenharmony_ci iris_resource_for_aspect(info->dst.resource, aspect); 487bf215546Sopenharmony_ci 488bf215546Sopenharmony_ci enum pipe_format src_pfmt = 489bf215546Sopenharmony_ci pipe_format_for_aspect(info->src.format, aspect); 490bf215546Sopenharmony_ci enum pipe_format dst_pfmt = 491bf215546Sopenharmony_ci pipe_format_for_aspect(info->dst.format, aspect); 492bf215546Sopenharmony_ci 493bf215546Sopenharmony_ci struct iris_format_info src_fmt = 494bf215546Sopenharmony_ci iris_format_for_usage(devinfo, src_pfmt, ISL_SURF_USAGE_TEXTURE_BIT); 495bf215546Sopenharmony_ci enum isl_aux_usage src_aux_usage = 496bf215546Sopenharmony_ci iris_resource_texture_aux_usage(ice, src_res, src_fmt.fmt); 497bf215546Sopenharmony_ci 498bf215546Sopenharmony_ci iris_resource_prepare_texture(ice, src_res, src_fmt.fmt, 499bf215546Sopenharmony_ci info->src.level, 1, info->src.box.z, 500bf215546Sopenharmony_ci info->src.box.depth); 501bf215546Sopenharmony_ci iris_emit_buffer_barrier_for(batch, src_res->bo, 502bf215546Sopenharmony_ci IRIS_DOMAIN_SAMPLER_READ); 503bf215546Sopenharmony_ci 504bf215546Sopenharmony_ci struct iris_format_info dst_fmt = 505bf215546Sopenharmony_ci iris_format_for_usage(devinfo, dst_pfmt, 506bf215546Sopenharmony_ci ISL_SURF_USAGE_RENDER_TARGET_BIT); 507bf215546Sopenharmony_ci enum isl_aux_usage dst_aux_usage = 508bf215546Sopenharmony_ci iris_resource_render_aux_usage(ice, dst_res, info->dst.level, 509bf215546Sopenharmony_ci dst_fmt.fmt, false); 510bf215546Sopenharmony_ci 511bf215546Sopenharmony_ci struct blorp_surf src_surf, dst_surf; 512bf215546Sopenharmony_ci iris_blorp_surf_for_resource(&screen->isl_dev, &src_surf, 513bf215546Sopenharmony_ci &src_res->base.b, src_aux_usage, 514bf215546Sopenharmony_ci info->src.level, false); 515bf215546Sopenharmony_ci iris_blorp_surf_for_resource(&screen->isl_dev, &dst_surf, 516bf215546Sopenharmony_ci &dst_res->base.b, dst_aux_usage, 517bf215546Sopenharmony_ci info->dst.level, true); 518bf215546Sopenharmony_ci 519bf215546Sopenharmony_ci iris_resource_prepare_render(ice, dst_res, info->dst.level, 520bf215546Sopenharmony_ci info->dst.box.z, info->dst.box.depth, 521bf215546Sopenharmony_ci dst_aux_usage); 522bf215546Sopenharmony_ci iris_emit_buffer_barrier_for(batch, dst_res->bo, 523bf215546Sopenharmony_ci IRIS_DOMAIN_RENDER_WRITE); 524bf215546Sopenharmony_ci 525bf215546Sopenharmony_ci if (iris_batch_references(batch, src_res->bo)) 526bf215546Sopenharmony_ci tex_cache_flush_hack(batch, src_fmt.fmt, src_res->surf.format); 527bf215546Sopenharmony_ci 528bf215546Sopenharmony_ci if (dst_res->base.b.target == PIPE_BUFFER) { 529bf215546Sopenharmony_ci util_range_add(&dst_res->base.b, &dst_res->valid_buffer_range, 530bf215546Sopenharmony_ci dst_x0, dst_x1); 531bf215546Sopenharmony_ci } 532bf215546Sopenharmony_ci 533bf215546Sopenharmony_ci for (int slice = 0; slice < info->dst.box.depth; slice++) { 534bf215546Sopenharmony_ci unsigned dst_z = info->dst.box.z + slice; 535bf215546Sopenharmony_ci float src_z = info->src.box.z + slice * src_z_step + 536bf215546Sopenharmony_ci depth_center_offset; 537bf215546Sopenharmony_ci 538bf215546Sopenharmony_ci iris_batch_maybe_flush(batch, 1500); 539bf215546Sopenharmony_ci iris_batch_sync_region_start(batch); 540bf215546Sopenharmony_ci 541bf215546Sopenharmony_ci blorp_blit(&blorp_batch, 542bf215546Sopenharmony_ci &src_surf, info->src.level, src_z, 543bf215546Sopenharmony_ci src_fmt.fmt, src_fmt.swizzle, 544bf215546Sopenharmony_ci &dst_surf, info->dst.level, dst_z, 545bf215546Sopenharmony_ci dst_fmt.fmt, dst_fmt.swizzle, 546bf215546Sopenharmony_ci src_x0, src_y0, src_x1, src_y1, 547bf215546Sopenharmony_ci dst_x0, dst_y0, dst_x1, dst_y1, 548bf215546Sopenharmony_ci filter, mirror_x, mirror_y); 549bf215546Sopenharmony_ci 550bf215546Sopenharmony_ci iris_batch_sync_region_end(batch); 551bf215546Sopenharmony_ci } 552bf215546Sopenharmony_ci 553bf215546Sopenharmony_ci tex_cache_flush_hack(batch, src_fmt.fmt, src_res->surf.format); 554bf215546Sopenharmony_ci 555bf215546Sopenharmony_ci iris_resource_finish_render(ice, dst_res, info->dst.level, 556bf215546Sopenharmony_ci info->dst.box.z, info->dst.box.depth, 557bf215546Sopenharmony_ci dst_aux_usage); 558bf215546Sopenharmony_ci } 559bf215546Sopenharmony_ci 560bf215546Sopenharmony_ci blorp_batch_finish(&blorp_batch); 561bf215546Sopenharmony_ci 562bf215546Sopenharmony_ci iris_dirty_for_history(ice, (struct iris_resource *)info->dst.resource); 563bf215546Sopenharmony_ci} 564bf215546Sopenharmony_ci 565bf215546Sopenharmony_cistatic void 566bf215546Sopenharmony_ciget_copy_region_aux_settings(struct iris_context *ice, 567bf215546Sopenharmony_ci const struct iris_batch *batch, 568bf215546Sopenharmony_ci struct iris_resource *res, 569bf215546Sopenharmony_ci unsigned level, 570bf215546Sopenharmony_ci enum isl_aux_usage *out_aux_usage, 571bf215546Sopenharmony_ci bool *out_clear_supported, 572bf215546Sopenharmony_ci bool is_dest) 573bf215546Sopenharmony_ci{ 574bf215546Sopenharmony_ci struct iris_screen *screen = (void *) ice->ctx.screen; 575bf215546Sopenharmony_ci struct intel_device_info *devinfo = &screen->devinfo; 576bf215546Sopenharmony_ci 577bf215546Sopenharmony_ci switch (res->aux.usage) { 578bf215546Sopenharmony_ci case ISL_AUX_USAGE_HIZ: 579bf215546Sopenharmony_ci case ISL_AUX_USAGE_HIZ_CCS: 580bf215546Sopenharmony_ci case ISL_AUX_USAGE_HIZ_CCS_WT: 581bf215546Sopenharmony_ci case ISL_AUX_USAGE_STC_CCS: 582bf215546Sopenharmony_ci if (is_dest) { 583bf215546Sopenharmony_ci *out_aux_usage = iris_resource_render_aux_usage(ice, res, level, 584bf215546Sopenharmony_ci res->surf.format, 585bf215546Sopenharmony_ci false); 586bf215546Sopenharmony_ci } else { 587bf215546Sopenharmony_ci *out_aux_usage = iris_resource_texture_aux_usage(ice, res, 588bf215546Sopenharmony_ci res->surf.format); 589bf215546Sopenharmony_ci } 590bf215546Sopenharmony_ci *out_clear_supported = isl_aux_usage_has_fast_clears(*out_aux_usage); 591bf215546Sopenharmony_ci break; 592bf215546Sopenharmony_ci case ISL_AUX_USAGE_MCS: 593bf215546Sopenharmony_ci case ISL_AUX_USAGE_MCS_CCS: 594bf215546Sopenharmony_ci if (!is_dest && !iris_can_sample_mcs_with_clear(devinfo, res)) { 595bf215546Sopenharmony_ci *out_aux_usage = res->aux.usage; 596bf215546Sopenharmony_ci *out_clear_supported = false; 597bf215546Sopenharmony_ci break; 598bf215546Sopenharmony_ci } 599bf215546Sopenharmony_ci FALLTHROUGH; 600bf215546Sopenharmony_ci case ISL_AUX_USAGE_CCS_E: 601bf215546Sopenharmony_ci case ISL_AUX_USAGE_GFX12_CCS_E: { 602bf215546Sopenharmony_ci /* blorp_copy may reinterpret the surface format and has limited support 603bf215546Sopenharmony_ci * for adjusting the clear color, so clear support may only be enabled 604bf215546Sopenharmony_ci * in some cases: 605bf215546Sopenharmony_ci * 606bf215546Sopenharmony_ci * - On gfx11+, the clear color is indirect and comes in two forms: a 607bf215546Sopenharmony_ci * 32bpc representation used for rendering and a pixel representation 608bf215546Sopenharmony_ci * used for sampling. blorp_copy doesn't change indirect clear colors, 609bf215546Sopenharmony_ci * so clears are only supported in the sampling case. 610bf215546Sopenharmony_ci * 611bf215546Sopenharmony_ci * - A clear color of zeroes holds the same meaning regardless of the 612bf215546Sopenharmony_ci * format. Although it could avoid more resolves, we don't use 613bf215546Sopenharmony_ci * isl_color_value_is_zero because the surface format used by 614bf215546Sopenharmony_ci * blorp_copy isn't guaranteed to access the same components as the 615bf215546Sopenharmony_ci * original format (e.g. A8_UNORM/R8_UINT). 616bf215546Sopenharmony_ci */ 617bf215546Sopenharmony_ci bool is_zero = clear_color_is_fully_zero(res); 618bf215546Sopenharmony_ci 619bf215546Sopenharmony_ci if (batch->name == IRIS_BATCH_BLITTER) { 620bf215546Sopenharmony_ci if (devinfo->verx10 >= 125) { 621bf215546Sopenharmony_ci *out_aux_usage = res->aux.usage; 622bf215546Sopenharmony_ci *out_clear_supported = is_zero; 623bf215546Sopenharmony_ci } else { 624bf215546Sopenharmony_ci *out_aux_usage = ISL_AUX_USAGE_NONE; 625bf215546Sopenharmony_ci *out_clear_supported = false; 626bf215546Sopenharmony_ci } 627bf215546Sopenharmony_ci } else { 628bf215546Sopenharmony_ci *out_aux_usage = res->aux.usage; 629bf215546Sopenharmony_ci *out_clear_supported = is_zero || (devinfo->ver >= 11 && !is_dest); 630bf215546Sopenharmony_ci } 631bf215546Sopenharmony_ci break; 632bf215546Sopenharmony_ci } 633bf215546Sopenharmony_ci default: 634bf215546Sopenharmony_ci *out_aux_usage = ISL_AUX_USAGE_NONE; 635bf215546Sopenharmony_ci *out_clear_supported = false; 636bf215546Sopenharmony_ci break; 637bf215546Sopenharmony_ci } 638bf215546Sopenharmony_ci} 639bf215546Sopenharmony_ci 640bf215546Sopenharmony_ci/** 641bf215546Sopenharmony_ci * Perform a GPU-based raw memory copy between compatible view classes. 642bf215546Sopenharmony_ci * 643bf215546Sopenharmony_ci * Does not perform any flushing - the new data may still be left in the 644bf215546Sopenharmony_ci * render cache, and old data may remain in other caches. 645bf215546Sopenharmony_ci * 646bf215546Sopenharmony_ci * Wraps blorp_copy() and blorp_buffer_copy(). 647bf215546Sopenharmony_ci */ 648bf215546Sopenharmony_civoid 649bf215546Sopenharmony_ciiris_copy_region(struct blorp_context *blorp, 650bf215546Sopenharmony_ci struct iris_batch *batch, 651bf215546Sopenharmony_ci struct pipe_resource *dst, 652bf215546Sopenharmony_ci unsigned dst_level, 653bf215546Sopenharmony_ci unsigned dstx, unsigned dsty, unsigned dstz, 654bf215546Sopenharmony_ci struct pipe_resource *src, 655bf215546Sopenharmony_ci unsigned src_level, 656bf215546Sopenharmony_ci const struct pipe_box *src_box) 657bf215546Sopenharmony_ci{ 658bf215546Sopenharmony_ci struct blorp_batch blorp_batch; 659bf215546Sopenharmony_ci struct iris_context *ice = blorp->driver_ctx; 660bf215546Sopenharmony_ci struct iris_screen *screen = (void *) ice->ctx.screen; 661bf215546Sopenharmony_ci struct iris_resource *src_res = (void *) src; 662bf215546Sopenharmony_ci struct iris_resource *dst_res = (void *) dst; 663bf215546Sopenharmony_ci 664bf215546Sopenharmony_ci enum iris_domain write_domain = 665bf215546Sopenharmony_ci batch->name == IRIS_BATCH_BLITTER ? IRIS_DOMAIN_OTHER_WRITE 666bf215546Sopenharmony_ci : IRIS_DOMAIN_RENDER_WRITE; 667bf215546Sopenharmony_ci 668bf215546Sopenharmony_ci enum isl_aux_usage src_aux_usage, dst_aux_usage; 669bf215546Sopenharmony_ci bool src_clear_supported, dst_clear_supported; 670bf215546Sopenharmony_ci get_copy_region_aux_settings(ice, batch, src_res, src_level, 671bf215546Sopenharmony_ci &src_aux_usage, &src_clear_supported, false); 672bf215546Sopenharmony_ci get_copy_region_aux_settings(ice, batch, dst_res, dst_level, 673bf215546Sopenharmony_ci &dst_aux_usage, &dst_clear_supported, true); 674bf215546Sopenharmony_ci 675bf215546Sopenharmony_ci if (iris_batch_references(batch, src_res->bo)) 676bf215546Sopenharmony_ci tex_cache_flush_hack(batch, ISL_FORMAT_UNSUPPORTED, src_res->surf.format); 677bf215546Sopenharmony_ci 678bf215546Sopenharmony_ci if (dst->target == PIPE_BUFFER) 679bf215546Sopenharmony_ci util_range_add(&dst_res->base.b, &dst_res->valid_buffer_range, dstx, dstx + src_box->width); 680bf215546Sopenharmony_ci 681bf215546Sopenharmony_ci enum blorp_batch_flags blorp_flags = iris_blorp_flags_for_batch(batch); 682bf215546Sopenharmony_ci 683bf215546Sopenharmony_ci blorp_batch_init(blorp, &blorp_batch, batch, blorp_flags); 684bf215546Sopenharmony_ci 685bf215546Sopenharmony_ci if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) { 686bf215546Sopenharmony_ci struct blorp_address src_addr = { 687bf215546Sopenharmony_ci .buffer = src_res->bo, .offset = src_res->offset + src_box->x, 688bf215546Sopenharmony_ci .mocs = iris_mocs(src_res->bo, &screen->isl_dev, 689bf215546Sopenharmony_ci ISL_SURF_USAGE_TEXTURE_BIT), 690bf215546Sopenharmony_ci .local_hint = iris_bo_likely_local(src_res->bo), 691bf215546Sopenharmony_ci }; 692bf215546Sopenharmony_ci struct blorp_address dst_addr = { 693bf215546Sopenharmony_ci .buffer = dst_res->bo, .offset = dst_res->offset + dstx, 694bf215546Sopenharmony_ci .reloc_flags = EXEC_OBJECT_WRITE, 695bf215546Sopenharmony_ci .mocs = iris_mocs(dst_res->bo, &screen->isl_dev, 696bf215546Sopenharmony_ci ISL_SURF_USAGE_RENDER_TARGET_BIT), 697bf215546Sopenharmony_ci .local_hint = iris_bo_likely_local(dst_res->bo), 698bf215546Sopenharmony_ci }; 699bf215546Sopenharmony_ci 700bf215546Sopenharmony_ci iris_emit_buffer_barrier_for(batch, src_res->bo, 701bf215546Sopenharmony_ci IRIS_DOMAIN_SAMPLER_READ); 702bf215546Sopenharmony_ci iris_emit_buffer_barrier_for(batch, dst_res->bo, write_domain); 703bf215546Sopenharmony_ci 704bf215546Sopenharmony_ci iris_batch_maybe_flush(batch, 1500); 705bf215546Sopenharmony_ci 706bf215546Sopenharmony_ci iris_batch_sync_region_start(batch); 707bf215546Sopenharmony_ci blorp_buffer_copy(&blorp_batch, src_addr, dst_addr, src_box->width); 708bf215546Sopenharmony_ci iris_batch_sync_region_end(batch); 709bf215546Sopenharmony_ci } else { 710bf215546Sopenharmony_ci // XXX: what about one surface being a buffer and not the other? 711bf215546Sopenharmony_ci 712bf215546Sopenharmony_ci struct blorp_surf src_surf, dst_surf; 713bf215546Sopenharmony_ci iris_blorp_surf_for_resource(&screen->isl_dev, &src_surf, 714bf215546Sopenharmony_ci src, src_aux_usage, src_level, false); 715bf215546Sopenharmony_ci iris_blorp_surf_for_resource(&screen->isl_dev, &dst_surf, 716bf215546Sopenharmony_ci dst, dst_aux_usage, dst_level, true); 717bf215546Sopenharmony_ci 718bf215546Sopenharmony_ci iris_resource_prepare_access(ice, src_res, src_level, 1, 719bf215546Sopenharmony_ci src_box->z, src_box->depth, 720bf215546Sopenharmony_ci src_aux_usage, src_clear_supported); 721bf215546Sopenharmony_ci iris_resource_prepare_access(ice, dst_res, dst_level, 1, 722bf215546Sopenharmony_ci dstz, src_box->depth, 723bf215546Sopenharmony_ci dst_aux_usage, dst_clear_supported); 724bf215546Sopenharmony_ci 725bf215546Sopenharmony_ci iris_emit_buffer_barrier_for(batch, src_res->bo, 726bf215546Sopenharmony_ci IRIS_DOMAIN_SAMPLER_READ); 727bf215546Sopenharmony_ci iris_emit_buffer_barrier_for(batch, dst_res->bo, write_domain); 728bf215546Sopenharmony_ci 729bf215546Sopenharmony_ci for (int slice = 0; slice < src_box->depth; slice++) { 730bf215546Sopenharmony_ci iris_batch_maybe_flush(batch, 1500); 731bf215546Sopenharmony_ci 732bf215546Sopenharmony_ci iris_batch_sync_region_start(batch); 733bf215546Sopenharmony_ci blorp_copy(&blorp_batch, &src_surf, src_level, src_box->z + slice, 734bf215546Sopenharmony_ci &dst_surf, dst_level, dstz + slice, 735bf215546Sopenharmony_ci src_box->x, src_box->y, dstx, dsty, 736bf215546Sopenharmony_ci src_box->width, src_box->height); 737bf215546Sopenharmony_ci iris_batch_sync_region_end(batch); 738bf215546Sopenharmony_ci } 739bf215546Sopenharmony_ci 740bf215546Sopenharmony_ci iris_resource_finish_write(ice, dst_res, dst_level, dstz, 741bf215546Sopenharmony_ci src_box->depth, dst_aux_usage); 742bf215546Sopenharmony_ci } 743bf215546Sopenharmony_ci 744bf215546Sopenharmony_ci blorp_batch_finish(&blorp_batch); 745bf215546Sopenharmony_ci 746bf215546Sopenharmony_ci tex_cache_flush_hack(batch, ISL_FORMAT_UNSUPPORTED, src_res->surf.format); 747bf215546Sopenharmony_ci} 748bf215546Sopenharmony_ci 749bf215546Sopenharmony_ci/** 750bf215546Sopenharmony_ci * The pipe->resource_copy_region() driver hook. 751bf215546Sopenharmony_ci * 752bf215546Sopenharmony_ci * This implements ARB_copy_image semantics - a raw memory copy between 753bf215546Sopenharmony_ci * compatible view classes. 754bf215546Sopenharmony_ci */ 755bf215546Sopenharmony_cistatic void 756bf215546Sopenharmony_ciiris_resource_copy_region(struct pipe_context *ctx, 757bf215546Sopenharmony_ci struct pipe_resource *p_dst, 758bf215546Sopenharmony_ci unsigned dst_level, 759bf215546Sopenharmony_ci unsigned dstx, unsigned dsty, unsigned dstz, 760bf215546Sopenharmony_ci struct pipe_resource *p_src, 761bf215546Sopenharmony_ci unsigned src_level, 762bf215546Sopenharmony_ci const struct pipe_box *src_box) 763bf215546Sopenharmony_ci{ 764bf215546Sopenharmony_ci struct iris_context *ice = (void *) ctx; 765bf215546Sopenharmony_ci struct iris_batch *batch = &ice->batches[IRIS_BATCH_RENDER]; 766bf215546Sopenharmony_ci 767bf215546Sopenharmony_ci iris_copy_region(&ice->blorp, batch, p_dst, dst_level, dstx, dsty, dstz, 768bf215546Sopenharmony_ci p_src, src_level, src_box); 769bf215546Sopenharmony_ci 770bf215546Sopenharmony_ci if (util_format_is_depth_and_stencil(p_dst->format) && 771bf215546Sopenharmony_ci util_format_has_stencil(util_format_description(p_src->format))) { 772bf215546Sopenharmony_ci struct iris_resource *junk, *s_src_res, *s_dst_res; 773bf215546Sopenharmony_ci iris_get_depth_stencil_resources(p_src, &junk, &s_src_res); 774bf215546Sopenharmony_ci iris_get_depth_stencil_resources(p_dst, &junk, &s_dst_res); 775bf215546Sopenharmony_ci 776bf215546Sopenharmony_ci iris_copy_region(&ice->blorp, batch, &s_dst_res->base.b, dst_level, dstx, 777bf215546Sopenharmony_ci dsty, dstz, &s_src_res->base.b, src_level, src_box); 778bf215546Sopenharmony_ci } 779bf215546Sopenharmony_ci 780bf215546Sopenharmony_ci iris_dirty_for_history(ice, (struct iris_resource *) p_dst); 781bf215546Sopenharmony_ci} 782bf215546Sopenharmony_ci 783bf215546Sopenharmony_civoid 784bf215546Sopenharmony_ciiris_init_blit_functions(struct pipe_context *ctx) 785bf215546Sopenharmony_ci{ 786bf215546Sopenharmony_ci ctx->blit = iris_blit; 787bf215546Sopenharmony_ci ctx->resource_copy_region = iris_resource_copy_region; 788bf215546Sopenharmony_ci} 789