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 "crocus_context.h" 34bf215546Sopenharmony_ci#include "crocus_resource.h" 35bf215546Sopenharmony_ci#include "crocus_screen.h" 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_civoid crocus_blitter_begin(struct crocus_context *ice, enum crocus_blitter_op op, bool render_cond) 38bf215546Sopenharmony_ci{ 39bf215546Sopenharmony_ci util_blitter_save_vertex_shader(ice->blitter, ice->shaders.uncompiled[MESA_SHADER_VERTEX]); 40bf215546Sopenharmony_ci util_blitter_save_tessctrl_shader(ice->blitter, ice->shaders.uncompiled[MESA_SHADER_TESS_CTRL]); 41bf215546Sopenharmony_ci util_blitter_save_tesseval_shader(ice->blitter, ice->shaders.uncompiled[MESA_SHADER_TESS_EVAL]); 42bf215546Sopenharmony_ci util_blitter_save_geometry_shader(ice->blitter, ice->shaders.uncompiled[MESA_SHADER_GEOMETRY]); 43bf215546Sopenharmony_ci util_blitter_save_so_targets(ice->blitter, ice->state.so_targets, 44bf215546Sopenharmony_ci (struct pipe_stream_output_target**)ice->state.so_target); 45bf215546Sopenharmony_ci util_blitter_save_vertex_buffer_slot(ice->blitter, ice->state.vertex_buffers); 46bf215546Sopenharmony_ci util_blitter_save_vertex_elements(ice->blitter, (void *)ice->state.cso_vertex_elements); 47bf215546Sopenharmony_ci if (op & CROCUS_SAVE_FRAGMENT_STATE) { 48bf215546Sopenharmony_ci util_blitter_save_blend(ice->blitter, ice->state.cso_blend); 49bf215546Sopenharmony_ci util_blitter_save_depth_stencil_alpha(ice->blitter, ice->state.cso_zsa); 50bf215546Sopenharmony_ci util_blitter_save_stencil_ref(ice->blitter, &ice->state.stencil_ref); 51bf215546Sopenharmony_ci util_blitter_save_fragment_shader(ice->blitter, ice->shaders.uncompiled[MESA_SHADER_FRAGMENT]); 52bf215546Sopenharmony_ci util_blitter_save_sample_mask(ice->blitter, ice->state.sample_mask, 0); 53bf215546Sopenharmony_ci util_blitter_save_rasterizer(ice->blitter, ice->state.cso_rast); 54bf215546Sopenharmony_ci util_blitter_save_scissor(ice->blitter, &ice->state.scissors[0]); 55bf215546Sopenharmony_ci util_blitter_save_viewport(ice->blitter, &ice->state.viewports[0]); 56bf215546Sopenharmony_ci util_blitter_save_fragment_constant_buffer_slot(ice->blitter, &ice->state.shaders[MESA_SHADER_FRAGMENT].constbufs[0]); 57bf215546Sopenharmony_ci } 58bf215546Sopenharmony_ci 59bf215546Sopenharmony_ci if (!render_cond) 60bf215546Sopenharmony_ci util_blitter_save_render_condition(ice->blitter, 61bf215546Sopenharmony_ci (struct pipe_query *)ice->condition.query, 62bf215546Sopenharmony_ci ice->condition.condition, 63bf215546Sopenharmony_ci ice->condition.mode); 64bf215546Sopenharmony_ci 65bf215546Sopenharmony_ci// util_blitter_save_scissor(ice->blitter, &ice->scissors[0]); 66bf215546Sopenharmony_ci if (op & CROCUS_SAVE_FRAMEBUFFER) 67bf215546Sopenharmony_ci util_blitter_save_framebuffer(ice->blitter, &ice->state.framebuffer); 68bf215546Sopenharmony_ci 69bf215546Sopenharmony_ci if (op & CROCUS_SAVE_TEXTURES) { 70bf215546Sopenharmony_ci util_blitter_save_fragment_sampler_states(ice->blitter, 1, (void **)ice->state.shaders[MESA_SHADER_FRAGMENT].samplers); 71bf215546Sopenharmony_ci util_blitter_save_fragment_sampler_views(ice->blitter, 1, (struct pipe_sampler_view **)ice->state.shaders[MESA_SHADER_FRAGMENT].textures); 72bf215546Sopenharmony_ci } 73bf215546Sopenharmony_ci} 74bf215546Sopenharmony_ci 75bf215546Sopenharmony_ci/** 76bf215546Sopenharmony_ci * Helper function for handling mirror image blits. 77bf215546Sopenharmony_ci * 78bf215546Sopenharmony_ci * If coord0 > coord1, swap them and return "true" (mirrored). 79bf215546Sopenharmony_ci */ 80bf215546Sopenharmony_cistatic bool 81bf215546Sopenharmony_ciapply_mirror(float *coord0, float *coord1) 82bf215546Sopenharmony_ci{ 83bf215546Sopenharmony_ci if (*coord0 > *coord1) { 84bf215546Sopenharmony_ci float tmp = *coord0; 85bf215546Sopenharmony_ci *coord0 = *coord1; 86bf215546Sopenharmony_ci *coord1 = tmp; 87bf215546Sopenharmony_ci return true; 88bf215546Sopenharmony_ci } 89bf215546Sopenharmony_ci return false; 90bf215546Sopenharmony_ci} 91bf215546Sopenharmony_ci 92bf215546Sopenharmony_ci/** 93bf215546Sopenharmony_ci * Compute the number of pixels to clip for each side of a rect 94bf215546Sopenharmony_ci * 95bf215546Sopenharmony_ci * \param x0 The rect's left coordinate 96bf215546Sopenharmony_ci * \param y0 The rect's bottom coordinate 97bf215546Sopenharmony_ci * \param x1 The rect's right coordinate 98bf215546Sopenharmony_ci * \param y1 The rect's top coordinate 99bf215546Sopenharmony_ci * \param min_x The clipping region's left coordinate 100bf215546Sopenharmony_ci * \param min_y The clipping region's bottom coordinate 101bf215546Sopenharmony_ci * \param max_x The clipping region's right coordinate 102bf215546Sopenharmony_ci * \param max_y The clipping region's top coordinate 103bf215546Sopenharmony_ci * \param clipped_x0 The number of pixels to clip from the left side 104bf215546Sopenharmony_ci * \param clipped_y0 The number of pixels to clip from the bottom side 105bf215546Sopenharmony_ci * \param clipped_x1 The number of pixels to clip from the right side 106bf215546Sopenharmony_ci * \param clipped_y1 The number of pixels to clip from the top side 107bf215546Sopenharmony_ci * 108bf215546Sopenharmony_ci * \return false if we clip everything away, true otherwise 109bf215546Sopenharmony_ci */ 110bf215546Sopenharmony_cistatic inline bool 111bf215546Sopenharmony_cicompute_pixels_clipped(float x0, float y0, float x1, float y1, 112bf215546Sopenharmony_ci float min_x, float min_y, float max_x, float max_y, 113bf215546Sopenharmony_ci float *clipped_x0, float *clipped_y0, 114bf215546Sopenharmony_ci float *clipped_x1, float *clipped_y1) 115bf215546Sopenharmony_ci{ 116bf215546Sopenharmony_ci /* If we are going to clip everything away, stop. */ 117bf215546Sopenharmony_ci if (!(min_x <= max_x && 118bf215546Sopenharmony_ci min_y <= max_y && 119bf215546Sopenharmony_ci x0 <= max_x && 120bf215546Sopenharmony_ci y0 <= max_y && 121bf215546Sopenharmony_ci min_x <= x1 && 122bf215546Sopenharmony_ci min_y <= y1 && 123bf215546Sopenharmony_ci x0 <= x1 && 124bf215546Sopenharmony_ci y0 <= y1)) { 125bf215546Sopenharmony_ci return false; 126bf215546Sopenharmony_ci } 127bf215546Sopenharmony_ci 128bf215546Sopenharmony_ci if (x0 < min_x) 129bf215546Sopenharmony_ci *clipped_x0 = min_x - x0; 130bf215546Sopenharmony_ci else 131bf215546Sopenharmony_ci *clipped_x0 = 0; 132bf215546Sopenharmony_ci if (max_x < x1) 133bf215546Sopenharmony_ci *clipped_x1 = x1 - max_x; 134bf215546Sopenharmony_ci else 135bf215546Sopenharmony_ci *clipped_x1 = 0; 136bf215546Sopenharmony_ci 137bf215546Sopenharmony_ci if (y0 < min_y) 138bf215546Sopenharmony_ci *clipped_y0 = min_y - y0; 139bf215546Sopenharmony_ci else 140bf215546Sopenharmony_ci *clipped_y0 = 0; 141bf215546Sopenharmony_ci if (max_y < y1) 142bf215546Sopenharmony_ci *clipped_y1 = y1 - max_y; 143bf215546Sopenharmony_ci else 144bf215546Sopenharmony_ci *clipped_y1 = 0; 145bf215546Sopenharmony_ci 146bf215546Sopenharmony_ci return true; 147bf215546Sopenharmony_ci} 148bf215546Sopenharmony_ci 149bf215546Sopenharmony_ci/** 150bf215546Sopenharmony_ci * Clips a coordinate (left, right, top or bottom) for the src or dst rect 151bf215546Sopenharmony_ci * (whichever requires the largest clip) and adjusts the coordinate 152bf215546Sopenharmony_ci * for the other rect accordingly. 153bf215546Sopenharmony_ci * 154bf215546Sopenharmony_ci * \param mirror true if mirroring is required 155bf215546Sopenharmony_ci * \param src the source rect coordinate (for example src_x0) 156bf215546Sopenharmony_ci * \param dst0 the dst rect coordinate (for example dst_x0) 157bf215546Sopenharmony_ci * \param dst1 the opposite dst rect coordinate (for example dst_x1) 158bf215546Sopenharmony_ci * \param clipped_dst0 number of pixels to clip from the dst coordinate 159bf215546Sopenharmony_ci * \param clipped_dst1 number of pixels to clip from the opposite dst coordinate 160bf215546Sopenharmony_ci * \param scale the src vs dst scale involved for that coordinate 161bf215546Sopenharmony_ci * \param is_left_or_bottom true if we are clipping the left or bottom sides 162bf215546Sopenharmony_ci * of the rect. 163bf215546Sopenharmony_ci */ 164bf215546Sopenharmony_cistatic void 165bf215546Sopenharmony_ciclip_coordinates(bool mirror, 166bf215546Sopenharmony_ci float *src, float *dst0, float *dst1, 167bf215546Sopenharmony_ci float clipped_dst0, 168bf215546Sopenharmony_ci float clipped_dst1, 169bf215546Sopenharmony_ci float scale, 170bf215546Sopenharmony_ci bool is_left_or_bottom) 171bf215546Sopenharmony_ci{ 172bf215546Sopenharmony_ci /* When clipping we need to add or subtract pixels from the original 173bf215546Sopenharmony_ci * coordinates depending on whether we are acting on the left/bottom 174bf215546Sopenharmony_ci * or right/top sides of the rect respectively. We assume we have to 175bf215546Sopenharmony_ci * add them in the code below, and multiply by -1 when we should 176bf215546Sopenharmony_ci * subtract. 177bf215546Sopenharmony_ci */ 178bf215546Sopenharmony_ci int mult = is_left_or_bottom ? 1 : -1; 179bf215546Sopenharmony_ci 180bf215546Sopenharmony_ci if (!mirror) { 181bf215546Sopenharmony_ci *dst0 += clipped_dst0 * mult; 182bf215546Sopenharmony_ci *src += clipped_dst0 * scale * mult; 183bf215546Sopenharmony_ci } else { 184bf215546Sopenharmony_ci *dst1 -= clipped_dst1 * mult; 185bf215546Sopenharmony_ci *src += clipped_dst1 * scale * mult; 186bf215546Sopenharmony_ci } 187bf215546Sopenharmony_ci} 188bf215546Sopenharmony_ci 189bf215546Sopenharmony_ci/** 190bf215546Sopenharmony_ci * Apply a scissor rectangle to blit coordinates. 191bf215546Sopenharmony_ci * 192bf215546Sopenharmony_ci * Returns true if the blit was entirely scissored away. 193bf215546Sopenharmony_ci */ 194bf215546Sopenharmony_cistatic bool 195bf215546Sopenharmony_ciapply_blit_scissor(const struct pipe_scissor_state *scissor, 196bf215546Sopenharmony_ci float *src_x0, float *src_y0, 197bf215546Sopenharmony_ci float *src_x1, float *src_y1, 198bf215546Sopenharmony_ci float *dst_x0, float *dst_y0, 199bf215546Sopenharmony_ci float *dst_x1, float *dst_y1, 200bf215546Sopenharmony_ci bool mirror_x, bool mirror_y) 201bf215546Sopenharmony_ci{ 202bf215546Sopenharmony_ci float clip_dst_x0, clip_dst_x1, clip_dst_y0, clip_dst_y1; 203bf215546Sopenharmony_ci 204bf215546Sopenharmony_ci /* Compute number of pixels to scissor away. */ 205bf215546Sopenharmony_ci if (!compute_pixels_clipped(*dst_x0, *dst_y0, *dst_x1, *dst_y1, 206bf215546Sopenharmony_ci scissor->minx, scissor->miny, 207bf215546Sopenharmony_ci scissor->maxx, scissor->maxy, 208bf215546Sopenharmony_ci &clip_dst_x0, &clip_dst_y0, 209bf215546Sopenharmony_ci &clip_dst_x1, &clip_dst_y1)) 210bf215546Sopenharmony_ci return true; 211bf215546Sopenharmony_ci 212bf215546Sopenharmony_ci // XXX: comments assume source clipping, which we don't do 213bf215546Sopenharmony_ci 214bf215546Sopenharmony_ci /* When clipping any of the two rects we need to adjust the coordinates 215bf215546Sopenharmony_ci * in the other rect considering the scaling factor involved. To obtain 216bf215546Sopenharmony_ci * the best precision we want to make sure that we only clip once per 217bf215546Sopenharmony_ci * side to avoid accumulating errors due to the scaling adjustment. 218bf215546Sopenharmony_ci * 219bf215546Sopenharmony_ci * For example, if src_x0 and dst_x0 need both to be clipped we want to 220bf215546Sopenharmony_ci * avoid the situation where we clip src_x0 first, then adjust dst_x0 221bf215546Sopenharmony_ci * accordingly but then we realize that the resulting dst_x0 still needs 222bf215546Sopenharmony_ci * to be clipped, so we clip dst_x0 and adjust src_x0 again. Because we are 223bf215546Sopenharmony_ci * applying scaling factors to adjust the coordinates in each clipping 224bf215546Sopenharmony_ci * pass we lose some precision and that can affect the results of the 225bf215546Sopenharmony_ci * blorp blit operation slightly. What we want to do here is detect the 226bf215546Sopenharmony_ci * rect that we should clip first for each side so that when we adjust 227bf215546Sopenharmony_ci * the other rect we ensure the resulting coordinate does not need to be 228bf215546Sopenharmony_ci * clipped again. 229bf215546Sopenharmony_ci * 230bf215546Sopenharmony_ci * The code below implements this by comparing the number of pixels that 231bf215546Sopenharmony_ci * we need to clip for each side of both rects considering the scales 232bf215546Sopenharmony_ci * involved. For example, clip_src_x0 represents the number of pixels 233bf215546Sopenharmony_ci * to be clipped for the src rect's left side, so if clip_src_x0 = 5, 234bf215546Sopenharmony_ci * clip_dst_x0 = 4 and scale_x = 2 it means that we are clipping more 235bf215546Sopenharmony_ci * from the dst rect so we should clip dst_x0 only and adjust src_x0. 236bf215546Sopenharmony_ci * This is because clipping 4 pixels in the dst is equivalent to 237bf215546Sopenharmony_ci * clipping 4 * 2 = 8 > 5 in the src. 238bf215546Sopenharmony_ci */ 239bf215546Sopenharmony_ci 240bf215546Sopenharmony_ci if (*src_x0 == *src_x1 || *src_y0 == *src_y1 241bf215546Sopenharmony_ci || *dst_x0 == *dst_x1 || *dst_y0 == *dst_y1) 242bf215546Sopenharmony_ci return true; 243bf215546Sopenharmony_ci 244bf215546Sopenharmony_ci float scale_x = (float) (*src_x1 - *src_x0) / (*dst_x1 - *dst_x0); 245bf215546Sopenharmony_ci float scale_y = (float) (*src_y1 - *src_y0) / (*dst_y1 - *dst_y0); 246bf215546Sopenharmony_ci 247bf215546Sopenharmony_ci /* Clip left side */ 248bf215546Sopenharmony_ci clip_coordinates(mirror_x, src_x0, dst_x0, dst_x1, 249bf215546Sopenharmony_ci clip_dst_x0, clip_dst_x1, scale_x, true); 250bf215546Sopenharmony_ci 251bf215546Sopenharmony_ci /* Clip right side */ 252bf215546Sopenharmony_ci clip_coordinates(mirror_x, src_x1, dst_x1, dst_x0, 253bf215546Sopenharmony_ci clip_dst_x1, clip_dst_x0, scale_x, false); 254bf215546Sopenharmony_ci 255bf215546Sopenharmony_ci /* Clip bottom side */ 256bf215546Sopenharmony_ci clip_coordinates(mirror_y, src_y0, dst_y0, dst_y1, 257bf215546Sopenharmony_ci clip_dst_y0, clip_dst_y1, scale_y, true); 258bf215546Sopenharmony_ci 259bf215546Sopenharmony_ci /* Clip top side */ 260bf215546Sopenharmony_ci clip_coordinates(mirror_y, src_y1, dst_y1, dst_y0, 261bf215546Sopenharmony_ci clip_dst_y1, clip_dst_y0, scale_y, false); 262bf215546Sopenharmony_ci 263bf215546Sopenharmony_ci /* Check for invalid bounds 264bf215546Sopenharmony_ci * Can't blit for 0-dimensions 265bf215546Sopenharmony_ci */ 266bf215546Sopenharmony_ci return *src_x0 == *src_x1 || *src_y0 == *src_y1 267bf215546Sopenharmony_ci || *dst_x0 == *dst_x1 || *dst_y0 == *dst_y1; 268bf215546Sopenharmony_ci} 269bf215546Sopenharmony_ci 270bf215546Sopenharmony_civoid 271bf215546Sopenharmony_cicrocus_blorp_surf_for_resource(struct crocus_vtable *vtbl, 272bf215546Sopenharmony_ci struct isl_device *isl_dev, 273bf215546Sopenharmony_ci struct blorp_surf *surf, 274bf215546Sopenharmony_ci struct pipe_resource *p_res, 275bf215546Sopenharmony_ci enum isl_aux_usage aux_usage, 276bf215546Sopenharmony_ci unsigned level, 277bf215546Sopenharmony_ci bool is_render_target) 278bf215546Sopenharmony_ci{ 279bf215546Sopenharmony_ci struct crocus_resource *res = (void *) p_res; 280bf215546Sopenharmony_ci 281bf215546Sopenharmony_ci assert(!crocus_resource_unfinished_aux_import(res)); 282bf215546Sopenharmony_ci 283bf215546Sopenharmony_ci if (isl_aux_usage_has_hiz(aux_usage) && 284bf215546Sopenharmony_ci !crocus_resource_level_has_hiz(res, level)) 285bf215546Sopenharmony_ci aux_usage = ISL_AUX_USAGE_NONE; 286bf215546Sopenharmony_ci 287bf215546Sopenharmony_ci *surf = (struct blorp_surf) { 288bf215546Sopenharmony_ci .surf = &res->surf, 289bf215546Sopenharmony_ci .addr = (struct blorp_address) { 290bf215546Sopenharmony_ci .buffer = res->bo, 291bf215546Sopenharmony_ci .offset = res->offset, 292bf215546Sopenharmony_ci .reloc_flags = is_render_target ? EXEC_OBJECT_WRITE : 0, 293bf215546Sopenharmony_ci .mocs = crocus_mocs(res->bo, isl_dev), 294bf215546Sopenharmony_ci }, 295bf215546Sopenharmony_ci .aux_usage = aux_usage, 296bf215546Sopenharmony_ci }; 297bf215546Sopenharmony_ci 298bf215546Sopenharmony_ci if (aux_usage != ISL_AUX_USAGE_NONE) { 299bf215546Sopenharmony_ci surf->aux_surf = &res->aux.surf; 300bf215546Sopenharmony_ci surf->aux_addr = (struct blorp_address) { 301bf215546Sopenharmony_ci .buffer = res->aux.bo, 302bf215546Sopenharmony_ci .offset = res->aux.offset, 303bf215546Sopenharmony_ci .reloc_flags = is_render_target ? EXEC_OBJECT_WRITE : 0, 304bf215546Sopenharmony_ci .mocs = crocus_mocs(res->bo, isl_dev), 305bf215546Sopenharmony_ci }; 306bf215546Sopenharmony_ci surf->clear_color = 307bf215546Sopenharmony_ci crocus_resource_get_clear_color(res); 308bf215546Sopenharmony_ci } 309bf215546Sopenharmony_ci} 310bf215546Sopenharmony_ci 311bf215546Sopenharmony_cistatic void 312bf215546Sopenharmony_citex_cache_flush_hack(struct crocus_batch *batch, 313bf215546Sopenharmony_ci enum isl_format view_format, 314bf215546Sopenharmony_ci enum isl_format surf_format) 315bf215546Sopenharmony_ci{ 316bf215546Sopenharmony_ci /* The WaSamplerCacheFlushBetweenRedescribedSurfaceReads workaround says: 317bf215546Sopenharmony_ci * 318bf215546Sopenharmony_ci * "Currently Sampler assumes that a surface would not have two 319bf215546Sopenharmony_ci * different format associate with it. It will not properly cache 320bf215546Sopenharmony_ci * the different views in the MT cache, causing a data corruption." 321bf215546Sopenharmony_ci * 322bf215546Sopenharmony_ci * We may need to handle this for texture views in general someday, but 323bf215546Sopenharmony_ci * for now we handle it here, as it hurts copies and blits particularly 324bf215546Sopenharmony_ci * badly because they ofter reinterpret formats. 325bf215546Sopenharmony_ci * 326bf215546Sopenharmony_ci * If the BO hasn't been referenced yet this batch, we assume that the 327bf215546Sopenharmony_ci * texture cache doesn't contain any relevant data nor need flushing. 328bf215546Sopenharmony_ci * 329bf215546Sopenharmony_ci * Icelake (Gen11+) claims to fix this issue, but seems to still have 330bf215546Sopenharmony_ci * issues with ASTC formats. 331bf215546Sopenharmony_ci */ 332bf215546Sopenharmony_ci bool need_flush = view_format != surf_format; 333bf215546Sopenharmony_ci if (!need_flush) 334bf215546Sopenharmony_ci return; 335bf215546Sopenharmony_ci 336bf215546Sopenharmony_ci const char *reason = 337bf215546Sopenharmony_ci "workaround: WaSamplerCacheFlushBetweenRedescribedSurfaceReads"; 338bf215546Sopenharmony_ci 339bf215546Sopenharmony_ci crocus_emit_pipe_control_flush(batch, reason, PIPE_CONTROL_CS_STALL); 340bf215546Sopenharmony_ci crocus_emit_pipe_control_flush(batch, reason, 341bf215546Sopenharmony_ci PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE); 342bf215546Sopenharmony_ci} 343bf215546Sopenharmony_ci 344bf215546Sopenharmony_cistatic struct crocus_resource * 345bf215546Sopenharmony_cicrocus_resource_for_aspect(const struct intel_device_info *devinfo, 346bf215546Sopenharmony_ci struct pipe_resource *p_res, unsigned pipe_mask) 347bf215546Sopenharmony_ci{ 348bf215546Sopenharmony_ci if (pipe_mask == PIPE_MASK_S) { 349bf215546Sopenharmony_ci struct crocus_resource *junk, *s_res; 350bf215546Sopenharmony_ci crocus_get_depth_stencil_resources(devinfo, p_res, &junk, &s_res); 351bf215546Sopenharmony_ci return s_res; 352bf215546Sopenharmony_ci } else { 353bf215546Sopenharmony_ci return (struct crocus_resource *)p_res; 354bf215546Sopenharmony_ci } 355bf215546Sopenharmony_ci} 356bf215546Sopenharmony_ci 357bf215546Sopenharmony_cistatic enum pipe_format 358bf215546Sopenharmony_cipipe_format_for_aspect(enum pipe_format format, unsigned pipe_mask) 359bf215546Sopenharmony_ci{ 360bf215546Sopenharmony_ci if (pipe_mask == PIPE_MASK_S) { 361bf215546Sopenharmony_ci return util_format_stencil_only(format); 362bf215546Sopenharmony_ci } else if (pipe_mask == PIPE_MASK_Z) { 363bf215546Sopenharmony_ci return util_format_get_depth_only(format); 364bf215546Sopenharmony_ci } else { 365bf215546Sopenharmony_ci return format; 366bf215546Sopenharmony_ci } 367bf215546Sopenharmony_ci} 368bf215546Sopenharmony_ci 369bf215546Sopenharmony_cistatic void 370bf215546Sopenharmony_cicrocus_u_blitter(struct crocus_context *ice, 371bf215546Sopenharmony_ci const struct pipe_blit_info *info) 372bf215546Sopenharmony_ci{ 373bf215546Sopenharmony_ci struct pipe_blit_info dinfo = *info; 374bf215546Sopenharmony_ci if (!util_format_has_alpha(dinfo.dst.resource->format)) 375bf215546Sopenharmony_ci dinfo.mask &= ~PIPE_MASK_A; 376bf215546Sopenharmony_ci crocus_blitter_begin(ice, CROCUS_SAVE_FRAMEBUFFER | CROCUS_SAVE_TEXTURES | CROCUS_SAVE_FRAGMENT_STATE, info->render_condition_enable); 377bf215546Sopenharmony_ci util_blitter_blit(ice->blitter, &dinfo); 378bf215546Sopenharmony_ci} 379bf215546Sopenharmony_ci 380bf215546Sopenharmony_ci/** 381bf215546Sopenharmony_ci * The pipe->blit() driver hook. 382bf215546Sopenharmony_ci * 383bf215546Sopenharmony_ci * This performs a blit between two surfaces, which copies data but may 384bf215546Sopenharmony_ci * also perform format conversion, scaling, flipping, and so on. 385bf215546Sopenharmony_ci */ 386bf215546Sopenharmony_cistatic void 387bf215546Sopenharmony_cicrocus_blit(struct pipe_context *ctx, const struct pipe_blit_info *info) 388bf215546Sopenharmony_ci{ 389bf215546Sopenharmony_ci struct crocus_context *ice = (void *) ctx; 390bf215546Sopenharmony_ci struct crocus_screen *screen = (struct crocus_screen *)ctx->screen; 391bf215546Sopenharmony_ci const struct intel_device_info *devinfo = &screen->devinfo; 392bf215546Sopenharmony_ci struct crocus_batch *batch = &ice->batches[CROCUS_BATCH_RENDER]; 393bf215546Sopenharmony_ci enum blorp_batch_flags blorp_flags = 0; 394bf215546Sopenharmony_ci 395bf215546Sopenharmony_ci /* We don't support color masking. */ 396bf215546Sopenharmony_ci assert((info->mask & PIPE_MASK_RGBA) == PIPE_MASK_RGBA || 397bf215546Sopenharmony_ci (info->mask & PIPE_MASK_RGBA) == 0); 398bf215546Sopenharmony_ci 399bf215546Sopenharmony_ci if (info->render_condition_enable) 400bf215546Sopenharmony_ci if (!crocus_check_conditional_render(ice)) 401bf215546Sopenharmony_ci return; 402bf215546Sopenharmony_ci 403bf215546Sopenharmony_ci if (devinfo->ver <= 5) { 404bf215546Sopenharmony_ci if (!screen->vtbl.blit_blt(batch, info)) { 405bf215546Sopenharmony_ci 406bf215546Sopenharmony_ci if (!util_format_is_depth_or_stencil(info->src.resource->format) && 407bf215546Sopenharmony_ci info->dst.resource->target != PIPE_TEXTURE_3D) 408bf215546Sopenharmony_ci goto use_blorp; 409bf215546Sopenharmony_ci 410bf215546Sopenharmony_ci if (!util_blitter_is_blit_supported(ice->blitter, info)) { 411bf215546Sopenharmony_ci if (util_format_is_depth_or_stencil(info->src.resource->format)) { 412bf215546Sopenharmony_ci 413bf215546Sopenharmony_ci struct pipe_blit_info depth_blit = *info; 414bf215546Sopenharmony_ci depth_blit.mask = PIPE_MASK_Z; 415bf215546Sopenharmony_ci crocus_blitter_begin(ice, CROCUS_SAVE_FRAMEBUFFER | CROCUS_SAVE_TEXTURES | CROCUS_SAVE_FRAGMENT_STATE, info->render_condition_enable); 416bf215546Sopenharmony_ci util_blitter_blit(ice->blitter, &depth_blit); 417bf215546Sopenharmony_ci 418bf215546Sopenharmony_ci struct pipe_surface *dst_view, dst_templ; 419bf215546Sopenharmony_ci util_blitter_default_dst_texture(&dst_templ, info->dst.resource, info->dst.level, info->dst.box.z); 420bf215546Sopenharmony_ci dst_view = ctx->create_surface(ctx, info->dst.resource, &dst_templ); 421bf215546Sopenharmony_ci 422bf215546Sopenharmony_ci crocus_blitter_begin(ice, CROCUS_SAVE_FRAMEBUFFER | CROCUS_SAVE_TEXTURES | CROCUS_SAVE_FRAGMENT_STATE, info->render_condition_enable); 423bf215546Sopenharmony_ci 424bf215546Sopenharmony_ci util_blitter_clear_depth_stencil(ice->blitter, dst_view, PIPE_CLEAR_STENCIL, 425bf215546Sopenharmony_ci 0, 0, info->dst.box.x, info->dst.box.y, 426bf215546Sopenharmony_ci info->dst.box.width, info->dst.box.height); 427bf215546Sopenharmony_ci crocus_blitter_begin(ice, CROCUS_SAVE_FRAMEBUFFER | CROCUS_SAVE_TEXTURES | CROCUS_SAVE_FRAGMENT_STATE, info->render_condition_enable); 428bf215546Sopenharmony_ci util_blitter_stencil_fallback(ice->blitter, 429bf215546Sopenharmony_ci info->dst.resource, 430bf215546Sopenharmony_ci info->dst.level, 431bf215546Sopenharmony_ci &info->dst.box, 432bf215546Sopenharmony_ci info->src.resource, 433bf215546Sopenharmony_ci info->src.level, 434bf215546Sopenharmony_ci &info->src.box, NULL); 435bf215546Sopenharmony_ci 436bf215546Sopenharmony_ci pipe_surface_release(ctx, &dst_view); 437bf215546Sopenharmony_ci } 438bf215546Sopenharmony_ci return; 439bf215546Sopenharmony_ci } 440bf215546Sopenharmony_ci 441bf215546Sopenharmony_ci crocus_u_blitter(ice, info); 442bf215546Sopenharmony_ci } 443bf215546Sopenharmony_ci return; 444bf215546Sopenharmony_ci } 445bf215546Sopenharmony_ci 446bf215546Sopenharmony_ci if (devinfo->ver == 6) { 447bf215546Sopenharmony_ci if (info->src.resource->target == PIPE_TEXTURE_3D && 448bf215546Sopenharmony_ci info->dst.resource->target == PIPE_TEXTURE_3D) { 449bf215546Sopenharmony_ci crocus_u_blitter(ice, info); 450bf215546Sopenharmony_ci return; 451bf215546Sopenharmony_ci } 452bf215546Sopenharmony_ci } 453bf215546Sopenharmony_ci 454bf215546Sopenharmony_ciuse_blorp: 455bf215546Sopenharmony_ci if (info->render_condition_enable) { 456bf215546Sopenharmony_ci if (ice->state.predicate == CROCUS_PREDICATE_STATE_USE_BIT) 457bf215546Sopenharmony_ci blorp_flags |= BLORP_BATCH_PREDICATE_ENABLE; 458bf215546Sopenharmony_ci } 459bf215546Sopenharmony_ci 460bf215546Sopenharmony_ci float src_x0 = info->src.box.x; 461bf215546Sopenharmony_ci float src_x1 = info->src.box.x + info->src.box.width; 462bf215546Sopenharmony_ci float src_y0 = info->src.box.y; 463bf215546Sopenharmony_ci float src_y1 = info->src.box.y + info->src.box.height; 464bf215546Sopenharmony_ci float dst_x0 = info->dst.box.x; 465bf215546Sopenharmony_ci float dst_x1 = info->dst.box.x + info->dst.box.width; 466bf215546Sopenharmony_ci float dst_y0 = info->dst.box.y; 467bf215546Sopenharmony_ci float dst_y1 = info->dst.box.y + info->dst.box.height; 468bf215546Sopenharmony_ci bool mirror_x = apply_mirror(&src_x0, &src_x1); 469bf215546Sopenharmony_ci bool mirror_y = apply_mirror(&src_y0, &src_y1); 470bf215546Sopenharmony_ci enum blorp_filter filter; 471bf215546Sopenharmony_ci 472bf215546Sopenharmony_ci if (info->scissor_enable) { 473bf215546Sopenharmony_ci bool noop = apply_blit_scissor(&info->scissor, 474bf215546Sopenharmony_ci &src_x0, &src_y0, &src_x1, &src_y1, 475bf215546Sopenharmony_ci &dst_x0, &dst_y0, &dst_x1, &dst_y1, 476bf215546Sopenharmony_ci mirror_x, mirror_y); 477bf215546Sopenharmony_ci if (noop) 478bf215546Sopenharmony_ci return; 479bf215546Sopenharmony_ci } 480bf215546Sopenharmony_ci 481bf215546Sopenharmony_ci if (abs(info->dst.box.width) == abs(info->src.box.width) && 482bf215546Sopenharmony_ci abs(info->dst.box.height) == abs(info->src.box.height)) { 483bf215546Sopenharmony_ci if (info->src.resource->nr_samples > 1 && 484bf215546Sopenharmony_ci info->dst.resource->nr_samples <= 1) { 485bf215546Sopenharmony_ci /* The OpenGL ES 3.2 specification, section 16.2.1, says: 486bf215546Sopenharmony_ci * 487bf215546Sopenharmony_ci * "If the read framebuffer is multisampled (its effective 488bf215546Sopenharmony_ci * value of SAMPLE_BUFFERS is one) and the draw framebuffer 489bf215546Sopenharmony_ci * is not (its value of SAMPLE_BUFFERS is zero), the samples 490bf215546Sopenharmony_ci * corresponding to each pixel location in the source are 491bf215546Sopenharmony_ci * converted to a single sample before being written to the 492bf215546Sopenharmony_ci * destination. The filter parameter is ignored. If the 493bf215546Sopenharmony_ci * source formats are integer types or stencil values, a 494bf215546Sopenharmony_ci * single sample’s value is selected for each pixel. If the 495bf215546Sopenharmony_ci * source formats are floating-point or normalized types, 496bf215546Sopenharmony_ci * the sample values for each pixel are resolved in an 497bf215546Sopenharmony_ci * implementation-dependent manner. If the source formats 498bf215546Sopenharmony_ci * are depth values, sample values are resolved in an 499bf215546Sopenharmony_ci * implementation-dependent manner where the result will be 500bf215546Sopenharmony_ci * between the minimum and maximum depth values in the pixel." 501bf215546Sopenharmony_ci * 502bf215546Sopenharmony_ci * When selecting a single sample, we always choose sample 0. 503bf215546Sopenharmony_ci */ 504bf215546Sopenharmony_ci if (util_format_is_depth_or_stencil(info->src.format) || 505bf215546Sopenharmony_ci util_format_is_pure_integer(info->src.format)) { 506bf215546Sopenharmony_ci filter = BLORP_FILTER_SAMPLE_0; 507bf215546Sopenharmony_ci } else { 508bf215546Sopenharmony_ci filter = BLORP_FILTER_AVERAGE; 509bf215546Sopenharmony_ci } 510bf215546Sopenharmony_ci } else { 511bf215546Sopenharmony_ci /* The OpenGL 4.6 specification, section 18.3.1, says: 512bf215546Sopenharmony_ci * 513bf215546Sopenharmony_ci * "If the source and destination dimensions are identical, 514bf215546Sopenharmony_ci * no filtering is applied." 515bf215546Sopenharmony_ci * 516bf215546Sopenharmony_ci * Using BLORP_FILTER_NONE will also handle the upsample case by 517bf215546Sopenharmony_ci * replicating the one value in the source to all values in the 518bf215546Sopenharmony_ci * destination. 519bf215546Sopenharmony_ci */ 520bf215546Sopenharmony_ci filter = BLORP_FILTER_NONE; 521bf215546Sopenharmony_ci } 522bf215546Sopenharmony_ci } else if (info->filter == PIPE_TEX_FILTER_LINEAR) { 523bf215546Sopenharmony_ci filter = BLORP_FILTER_BILINEAR; 524bf215546Sopenharmony_ci } else { 525bf215546Sopenharmony_ci filter = BLORP_FILTER_NEAREST; 526bf215546Sopenharmony_ci } 527bf215546Sopenharmony_ci 528bf215546Sopenharmony_ci struct blorp_batch blorp_batch; 529bf215546Sopenharmony_ci blorp_batch_init(&ice->blorp, &blorp_batch, batch, blorp_flags); 530bf215546Sopenharmony_ci 531bf215546Sopenharmony_ci float src_z_step = (float)info->src.box.depth / (float)info->dst.box.depth; 532bf215546Sopenharmony_ci 533bf215546Sopenharmony_ci /* There is no interpolation to the pixel center during rendering, so 534bf215546Sopenharmony_ci * add the 0.5 offset ourselves here. 535bf215546Sopenharmony_ci */ 536bf215546Sopenharmony_ci float depth_center_offset = 0; 537bf215546Sopenharmony_ci if (info->src.resource->target == PIPE_TEXTURE_3D) 538bf215546Sopenharmony_ci depth_center_offset = 0.5 / info->dst.box.depth * info->src.box.depth; 539bf215546Sopenharmony_ci 540bf215546Sopenharmony_ci /* Perform a blit for each aspect requested by the caller. PIPE_MASK_R is 541bf215546Sopenharmony_ci * used to represent the color aspect. */ 542bf215546Sopenharmony_ci unsigned aspect_mask = info->mask & (PIPE_MASK_R | PIPE_MASK_ZS); 543bf215546Sopenharmony_ci while (aspect_mask) { 544bf215546Sopenharmony_ci unsigned aspect = 1 << u_bit_scan(&aspect_mask); 545bf215546Sopenharmony_ci 546bf215546Sopenharmony_ci struct crocus_resource *src_res = 547bf215546Sopenharmony_ci crocus_resource_for_aspect(devinfo, info->src.resource, aspect); 548bf215546Sopenharmony_ci struct crocus_resource *dst_res = 549bf215546Sopenharmony_ci crocus_resource_for_aspect(devinfo, info->dst.resource, aspect); 550bf215546Sopenharmony_ci 551bf215546Sopenharmony_ci enum pipe_format src_pfmt = 552bf215546Sopenharmony_ci pipe_format_for_aspect(info->src.format, aspect); 553bf215546Sopenharmony_ci enum pipe_format dst_pfmt = 554bf215546Sopenharmony_ci pipe_format_for_aspect(info->dst.format, aspect); 555bf215546Sopenharmony_ci 556bf215546Sopenharmony_ci if (crocus_resource_unfinished_aux_import(src_res)) 557bf215546Sopenharmony_ci crocus_resource_finish_aux_import(ctx->screen, src_res); 558bf215546Sopenharmony_ci if (crocus_resource_unfinished_aux_import(dst_res)) 559bf215546Sopenharmony_ci crocus_resource_finish_aux_import(ctx->screen, dst_res); 560bf215546Sopenharmony_ci 561bf215546Sopenharmony_ci struct crocus_format_info src_fmt = 562bf215546Sopenharmony_ci crocus_format_for_usage(devinfo, src_pfmt, ISL_SURF_USAGE_TEXTURE_BIT); 563bf215546Sopenharmony_ci enum isl_aux_usage src_aux_usage = 564bf215546Sopenharmony_ci crocus_resource_texture_aux_usage(src_res); 565bf215546Sopenharmony_ci 566bf215546Sopenharmony_ci crocus_resource_prepare_texture(ice, src_res, src_fmt.fmt, 567bf215546Sopenharmony_ci info->src.level, 1, info->src.box.z, 568bf215546Sopenharmony_ci info->src.box.depth); 569bf215546Sopenharmony_ci // crocus_emit_buffer_barrier_for(batch, src_res->bo, 570bf215546Sopenharmony_ci // CROCUS_DOMAIN_OTHER_READ); 571bf215546Sopenharmony_ci 572bf215546Sopenharmony_ci bool dst_aux_disable = false; 573bf215546Sopenharmony_ci /* on SNB blorp will use render target instead of depth 574bf215546Sopenharmony_ci * so disable HiZ. 575bf215546Sopenharmony_ci */ 576bf215546Sopenharmony_ci if (devinfo->ver <= 6 && util_format_is_depth_or_stencil(dst_pfmt)) 577bf215546Sopenharmony_ci dst_aux_disable = true; 578bf215546Sopenharmony_ci struct crocus_format_info dst_fmt = 579bf215546Sopenharmony_ci crocus_format_for_usage(devinfo, dst_pfmt, 580bf215546Sopenharmony_ci ISL_SURF_USAGE_RENDER_TARGET_BIT); 581bf215546Sopenharmony_ci enum isl_aux_usage dst_aux_usage = 582bf215546Sopenharmony_ci crocus_resource_render_aux_usage(ice, dst_res, info->dst.level, 583bf215546Sopenharmony_ci dst_fmt.fmt, dst_aux_disable); 584bf215546Sopenharmony_ci 585bf215546Sopenharmony_ci struct blorp_surf src_surf, dst_surf; 586bf215546Sopenharmony_ci crocus_blorp_surf_for_resource(&screen->vtbl, &screen->isl_dev, &src_surf, 587bf215546Sopenharmony_ci &src_res->base.b, src_aux_usage, 588bf215546Sopenharmony_ci info->src.level, false); 589bf215546Sopenharmony_ci crocus_blorp_surf_for_resource(&screen->vtbl, &screen->isl_dev, &dst_surf, 590bf215546Sopenharmony_ci &dst_res->base.b, dst_aux_usage, 591bf215546Sopenharmony_ci info->dst.level, true); 592bf215546Sopenharmony_ci 593bf215546Sopenharmony_ci crocus_resource_prepare_render(ice, dst_res, info->dst.level, 594bf215546Sopenharmony_ci info->dst.box.z, info->dst.box.depth, 595bf215546Sopenharmony_ci dst_aux_usage); 596bf215546Sopenharmony_ci // crocus_emit_buffer_barrier_for(batch, dst_res->bo, 597bf215546Sopenharmony_ci // CROCUS_DOMAIN_RENDER_WRITE); 598bf215546Sopenharmony_ci 599bf215546Sopenharmony_ci if (crocus_batch_references(batch, src_res->bo)) 600bf215546Sopenharmony_ci tex_cache_flush_hack(batch, src_fmt.fmt, src_res->surf.format); 601bf215546Sopenharmony_ci 602bf215546Sopenharmony_ci if (dst_res->base.b.target == PIPE_BUFFER) { 603bf215546Sopenharmony_ci util_range_add(&dst_res->base.b, &dst_res->valid_buffer_range, 604bf215546Sopenharmony_ci dst_x0, dst_x1); 605bf215546Sopenharmony_ci } 606bf215546Sopenharmony_ci 607bf215546Sopenharmony_ci struct isl_swizzle src_swiz = pipe_to_isl_swizzles(src_fmt.swizzles); 608bf215546Sopenharmony_ci struct isl_swizzle dst_swiz = pipe_to_isl_swizzles(dst_fmt.swizzles); 609bf215546Sopenharmony_ci 610bf215546Sopenharmony_ci for (int slice = 0; slice < info->dst.box.depth; slice++) { 611bf215546Sopenharmony_ci unsigned dst_z = info->dst.box.z + slice; 612bf215546Sopenharmony_ci float src_z = info->src.box.z + slice * src_z_step + 613bf215546Sopenharmony_ci depth_center_offset; 614bf215546Sopenharmony_ci 615bf215546Sopenharmony_ci crocus_batch_maybe_flush(batch, 1500); 616bf215546Sopenharmony_ci 617bf215546Sopenharmony_ci blorp_blit(&blorp_batch, 618bf215546Sopenharmony_ci &src_surf, info->src.level, src_z, 619bf215546Sopenharmony_ci src_fmt.fmt, src_swiz, 620bf215546Sopenharmony_ci &dst_surf, info->dst.level, dst_z, 621bf215546Sopenharmony_ci dst_fmt.fmt, dst_swiz, 622bf215546Sopenharmony_ci src_x0, src_y0, src_x1, src_y1, 623bf215546Sopenharmony_ci dst_x0, dst_y0, dst_x1, dst_y1, 624bf215546Sopenharmony_ci filter, mirror_x, mirror_y); 625bf215546Sopenharmony_ci 626bf215546Sopenharmony_ci } 627bf215546Sopenharmony_ci 628bf215546Sopenharmony_ci tex_cache_flush_hack(batch, src_fmt.fmt, src_res->surf.format); 629bf215546Sopenharmony_ci 630bf215546Sopenharmony_ci crocus_resource_finish_render(ice, dst_res, info->dst.level, 631bf215546Sopenharmony_ci info->dst.box.z, info->dst.box.depth, 632bf215546Sopenharmony_ci dst_aux_usage); 633bf215546Sopenharmony_ci } 634bf215546Sopenharmony_ci 635bf215546Sopenharmony_ci blorp_batch_finish(&blorp_batch); 636bf215546Sopenharmony_ci 637bf215546Sopenharmony_ci crocus_flush_and_dirty_for_history(ice, batch, (struct crocus_resource *) 638bf215546Sopenharmony_ci info->dst.resource, 639bf215546Sopenharmony_ci PIPE_CONTROL_RENDER_TARGET_FLUSH, 640bf215546Sopenharmony_ci "cache history: post-blit"); 641bf215546Sopenharmony_ci} 642bf215546Sopenharmony_ci 643bf215546Sopenharmony_cistatic void 644bf215546Sopenharmony_ciget_copy_region_aux_settings(struct crocus_resource *res, 645bf215546Sopenharmony_ci enum isl_aux_usage *out_aux_usage, 646bf215546Sopenharmony_ci bool is_render_target) 647bf215546Sopenharmony_ci{ 648bf215546Sopenharmony_ci switch (res->aux.usage) { 649bf215546Sopenharmony_ci case ISL_AUX_USAGE_MCS: 650bf215546Sopenharmony_ci /* A stencil resolve operation must be performed prior to doing resource 651bf215546Sopenharmony_ci * copies or used by CPU. 652bf215546Sopenharmony_ci * (see HSD 1209978162) 653bf215546Sopenharmony_ci */ 654bf215546Sopenharmony_ci if (is_render_target && isl_surf_usage_is_stencil(res->surf.usage)) { 655bf215546Sopenharmony_ci *out_aux_usage = ISL_AUX_USAGE_NONE; 656bf215546Sopenharmony_ci } else { 657bf215546Sopenharmony_ci *out_aux_usage = res->aux.usage; 658bf215546Sopenharmony_ci } 659bf215546Sopenharmony_ci break; 660bf215546Sopenharmony_ci default: 661bf215546Sopenharmony_ci *out_aux_usage = ISL_AUX_USAGE_NONE; 662bf215546Sopenharmony_ci break; 663bf215546Sopenharmony_ci } 664bf215546Sopenharmony_ci} 665bf215546Sopenharmony_ci 666bf215546Sopenharmony_ci/** 667bf215546Sopenharmony_ci * Perform a GPU-based raw memory copy between compatible view classes. 668bf215546Sopenharmony_ci * 669bf215546Sopenharmony_ci * Does not perform any flushing - the new data may still be left in the 670bf215546Sopenharmony_ci * render cache, and old data may remain in other caches. 671bf215546Sopenharmony_ci * 672bf215546Sopenharmony_ci * Wraps blorp_copy() and blorp_buffer_copy(). 673bf215546Sopenharmony_ci */ 674bf215546Sopenharmony_civoid 675bf215546Sopenharmony_cicrocus_copy_region(struct blorp_context *blorp, 676bf215546Sopenharmony_ci struct crocus_batch *batch, 677bf215546Sopenharmony_ci struct pipe_resource *dst, 678bf215546Sopenharmony_ci unsigned dst_level, 679bf215546Sopenharmony_ci unsigned dstx, unsigned dsty, unsigned dstz, 680bf215546Sopenharmony_ci struct pipe_resource *src, 681bf215546Sopenharmony_ci unsigned src_level, 682bf215546Sopenharmony_ci const struct pipe_box *src_box) 683bf215546Sopenharmony_ci{ 684bf215546Sopenharmony_ci struct blorp_batch blorp_batch; 685bf215546Sopenharmony_ci struct crocus_context *ice = blorp->driver_ctx; 686bf215546Sopenharmony_ci struct crocus_screen *screen = (void *) ice->ctx.screen; 687bf215546Sopenharmony_ci const struct intel_device_info *devinfo = &screen->devinfo; 688bf215546Sopenharmony_ci struct crocus_resource *src_res = (void *) src; 689bf215546Sopenharmony_ci struct crocus_resource *dst_res = (void *) dst; 690bf215546Sopenharmony_ci 691bf215546Sopenharmony_ci if (devinfo->ver <= 5) { 692bf215546Sopenharmony_ci if (screen->vtbl.copy_region_blt(batch, dst_res, 693bf215546Sopenharmony_ci dst_level, dstx, dsty, dstz, 694bf215546Sopenharmony_ci src_res, src_level, src_box)) 695bf215546Sopenharmony_ci return; 696bf215546Sopenharmony_ci } 697bf215546Sopenharmony_ci enum isl_aux_usage src_aux_usage, dst_aux_usage; 698bf215546Sopenharmony_ci get_copy_region_aux_settings(src_res, &src_aux_usage, 699bf215546Sopenharmony_ci false); 700bf215546Sopenharmony_ci get_copy_region_aux_settings(dst_res, &dst_aux_usage, 701bf215546Sopenharmony_ci true); 702bf215546Sopenharmony_ci 703bf215546Sopenharmony_ci if (crocus_batch_references(batch, src_res->bo)) 704bf215546Sopenharmony_ci tex_cache_flush_hack(batch, ISL_FORMAT_UNSUPPORTED, src_res->surf.format); 705bf215546Sopenharmony_ci 706bf215546Sopenharmony_ci if (dst->target == PIPE_BUFFER) 707bf215546Sopenharmony_ci util_range_add(&dst_res->base.b, &dst_res->valid_buffer_range, dstx, dstx + src_box->width); 708bf215546Sopenharmony_ci 709bf215546Sopenharmony_ci if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) { 710bf215546Sopenharmony_ci struct blorp_address src_addr = { 711bf215546Sopenharmony_ci .buffer = crocus_resource_bo(src), .offset = src_box->x, 712bf215546Sopenharmony_ci .mocs = crocus_mocs(src_res->bo, &screen->isl_dev), 713bf215546Sopenharmony_ci }; 714bf215546Sopenharmony_ci struct blorp_address dst_addr = { 715bf215546Sopenharmony_ci .buffer = crocus_resource_bo(dst), .offset = dstx, 716bf215546Sopenharmony_ci .mocs = crocus_mocs(dst_res->bo, &screen->isl_dev), 717bf215546Sopenharmony_ci .reloc_flags = EXEC_OBJECT_WRITE, 718bf215546Sopenharmony_ci }; 719bf215546Sopenharmony_ci 720bf215546Sopenharmony_ci crocus_batch_maybe_flush(batch, 1500); 721bf215546Sopenharmony_ci 722bf215546Sopenharmony_ci blorp_batch_init(&ice->blorp, &blorp_batch, batch, 0); 723bf215546Sopenharmony_ci blorp_buffer_copy(&blorp_batch, src_addr, dst_addr, src_box->width); 724bf215546Sopenharmony_ci blorp_batch_finish(&blorp_batch); 725bf215546Sopenharmony_ci } else { 726bf215546Sopenharmony_ci // XXX: what about one surface being a buffer and not the other? 727bf215546Sopenharmony_ci 728bf215546Sopenharmony_ci struct blorp_surf src_surf, dst_surf; 729bf215546Sopenharmony_ci crocus_blorp_surf_for_resource(&screen->vtbl, &screen->isl_dev, &src_surf, 730bf215546Sopenharmony_ci src, src_aux_usage, src_level, false); 731bf215546Sopenharmony_ci crocus_blorp_surf_for_resource(&screen->vtbl, &screen->isl_dev, &dst_surf, 732bf215546Sopenharmony_ci dst, dst_aux_usage, dst_level, true); 733bf215546Sopenharmony_ci 734bf215546Sopenharmony_ci crocus_resource_prepare_access(ice, src_res, src_level, 1, 735bf215546Sopenharmony_ci src_box->z, src_box->depth, 736bf215546Sopenharmony_ci src_aux_usage, false); 737bf215546Sopenharmony_ci crocus_resource_prepare_access(ice, dst_res, dst_level, 1, 738bf215546Sopenharmony_ci dstz, src_box->depth, 739bf215546Sopenharmony_ci dst_aux_usage, false); 740bf215546Sopenharmony_ci 741bf215546Sopenharmony_ci blorp_batch_init(&ice->blorp, &blorp_batch, batch, 0); 742bf215546Sopenharmony_ci 743bf215546Sopenharmony_ci for (int slice = 0; slice < src_box->depth; slice++) { 744bf215546Sopenharmony_ci crocus_batch_maybe_flush(batch, 1500); 745bf215546Sopenharmony_ci 746bf215546Sopenharmony_ci blorp_copy(&blorp_batch, &src_surf, src_level, src_box->z + slice, 747bf215546Sopenharmony_ci &dst_surf, dst_level, dstz + slice, 748bf215546Sopenharmony_ci src_box->x, src_box->y, dstx, dsty, 749bf215546Sopenharmony_ci src_box->width, src_box->height); 750bf215546Sopenharmony_ci } 751bf215546Sopenharmony_ci blorp_batch_finish(&blorp_batch); 752bf215546Sopenharmony_ci 753bf215546Sopenharmony_ci crocus_resource_finish_write(ice, dst_res, dst_level, dstz, 754bf215546Sopenharmony_ci src_box->depth, dst_aux_usage); 755bf215546Sopenharmony_ci } 756bf215546Sopenharmony_ci 757bf215546Sopenharmony_ci tex_cache_flush_hack(batch, ISL_FORMAT_UNSUPPORTED, src_res->surf.format); 758bf215546Sopenharmony_ci} 759bf215546Sopenharmony_ci 760bf215546Sopenharmony_ci/** 761bf215546Sopenharmony_ci * The pipe->resource_copy_region() driver hook. 762bf215546Sopenharmony_ci * 763bf215546Sopenharmony_ci * This implements ARB_copy_image semantics - a raw memory copy between 764bf215546Sopenharmony_ci * compatible view classes. 765bf215546Sopenharmony_ci */ 766bf215546Sopenharmony_cistatic void 767bf215546Sopenharmony_cicrocus_resource_copy_region(struct pipe_context *ctx, 768bf215546Sopenharmony_ci struct pipe_resource *p_dst, 769bf215546Sopenharmony_ci unsigned dst_level, 770bf215546Sopenharmony_ci unsigned dstx, unsigned dsty, unsigned dstz, 771bf215546Sopenharmony_ci struct pipe_resource *p_src, 772bf215546Sopenharmony_ci unsigned src_level, 773bf215546Sopenharmony_ci const struct pipe_box *src_box) 774bf215546Sopenharmony_ci{ 775bf215546Sopenharmony_ci struct crocus_context *ice = (void *) ctx; 776bf215546Sopenharmony_ci struct crocus_batch *batch = &ice->batches[CROCUS_BATCH_RENDER]; 777bf215546Sopenharmony_ci struct crocus_screen *screen = (struct crocus_screen *)ctx->screen; 778bf215546Sopenharmony_ci const struct intel_device_info *devinfo = &screen->devinfo; 779bf215546Sopenharmony_ci struct crocus_resource *src = (void *) p_src; 780bf215546Sopenharmony_ci struct crocus_resource *dst = (void *) p_dst; 781bf215546Sopenharmony_ci 782bf215546Sopenharmony_ci if (crocus_resource_unfinished_aux_import(src)) 783bf215546Sopenharmony_ci crocus_resource_finish_aux_import(ctx->screen, src); 784bf215546Sopenharmony_ci if (crocus_resource_unfinished_aux_import(dst)) 785bf215546Sopenharmony_ci crocus_resource_finish_aux_import(ctx->screen, dst); 786bf215546Sopenharmony_ci 787bf215546Sopenharmony_ci if (devinfo->ver < 6 && util_format_is_depth_or_stencil(p_dst->format)) { 788bf215546Sopenharmony_ci util_resource_copy_region(ctx, p_dst, dst_level, dstx, dsty, dstz, 789bf215546Sopenharmony_ci p_src, src_level, src_box); 790bf215546Sopenharmony_ci return; 791bf215546Sopenharmony_ci } 792bf215546Sopenharmony_ci crocus_copy_region(&ice->blorp, batch, p_dst, dst_level, dstx, dsty, dstz, 793bf215546Sopenharmony_ci p_src, src_level, src_box); 794bf215546Sopenharmony_ci 795bf215546Sopenharmony_ci if (util_format_is_depth_and_stencil(p_dst->format) && 796bf215546Sopenharmony_ci util_format_has_stencil(util_format_description(p_src->format)) && 797bf215546Sopenharmony_ci devinfo->ver >= 6) { 798bf215546Sopenharmony_ci struct crocus_resource *junk, *s_src_res, *s_dst_res; 799bf215546Sopenharmony_ci crocus_get_depth_stencil_resources(devinfo, p_src, &junk, &s_src_res); 800bf215546Sopenharmony_ci crocus_get_depth_stencil_resources(devinfo, p_dst, &junk, &s_dst_res); 801bf215546Sopenharmony_ci 802bf215546Sopenharmony_ci crocus_copy_region(&ice->blorp, batch, &s_dst_res->base.b, dst_level, dstx, 803bf215546Sopenharmony_ci dsty, dstz, &s_src_res->base.b, src_level, src_box); 804bf215546Sopenharmony_ci } 805bf215546Sopenharmony_ci 806bf215546Sopenharmony_ci crocus_flush_and_dirty_for_history(ice, batch, dst, 807bf215546Sopenharmony_ci PIPE_CONTROL_RENDER_TARGET_FLUSH, 808bf215546Sopenharmony_ci "cache history: post copy_region"); 809bf215546Sopenharmony_ci} 810bf215546Sopenharmony_ci 811bf215546Sopenharmony_civoid 812bf215546Sopenharmony_cicrocus_init_blit_functions(struct pipe_context *ctx) 813bf215546Sopenharmony_ci{ 814bf215546Sopenharmony_ci ctx->blit = crocus_blit; 815bf215546Sopenharmony_ci ctx->resource_copy_region = crocus_resource_copy_region; 816bf215546Sopenharmony_ci} 817