17ec681f3Smrg/* 27ec681f3Smrg * Copyright © 2017 Intel Corporation 37ec681f3Smrg * 47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 57ec681f3Smrg * copy of this software and associated documentation files (the "Software"), 67ec681f3Smrg * to deal in the Software without restriction, including without limitation 77ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 87ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the 97ec681f3Smrg * Software is furnished to do so, subject to the following conditions: 107ec681f3Smrg * 117ec681f3Smrg * The above copyright notice and this permission notice shall be included 127ec681f3Smrg * in all copies or substantial portions of the Software. 137ec681f3Smrg * 147ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 157ec681f3Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 167ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 177ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 187ec681f3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 197ec681f3Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 207ec681f3Smrg * DEALINGS IN THE SOFTWARE. 217ec681f3Smrg */ 227ec681f3Smrg 237ec681f3Smrg#include <stdio.h> 247ec681f3Smrg#include "pipe/p_defines.h" 257ec681f3Smrg#include "pipe/p_state.h" 267ec681f3Smrg#include "pipe/p_context.h" 277ec681f3Smrg#include "pipe/p_screen.h" 287ec681f3Smrg#include "util/format/u_format.h" 297ec681f3Smrg#include "util/u_inlines.h" 307ec681f3Smrg#include "util/u_surface.h" 317ec681f3Smrg#include "util/ralloc.h" 327ec681f3Smrg#include "intel/blorp/blorp.h" 337ec681f3Smrg#include "crocus_context.h" 347ec681f3Smrg#include "crocus_resource.h" 357ec681f3Smrg#include "crocus_screen.h" 367ec681f3Smrg 377ec681f3Smrgvoid crocus_blitter_begin(struct crocus_context *ice, enum crocus_blitter_op op, bool render_cond) 387ec681f3Smrg{ 397ec681f3Smrg util_blitter_save_vertex_shader(ice->blitter, ice->shaders.uncompiled[MESA_SHADER_VERTEX]); 407ec681f3Smrg util_blitter_save_tessctrl_shader(ice->blitter, ice->shaders.uncompiled[MESA_SHADER_TESS_CTRL]); 417ec681f3Smrg util_blitter_save_tesseval_shader(ice->blitter, ice->shaders.uncompiled[MESA_SHADER_TESS_EVAL]); 427ec681f3Smrg util_blitter_save_geometry_shader(ice->blitter, ice->shaders.uncompiled[MESA_SHADER_GEOMETRY]); 437ec681f3Smrg util_blitter_save_so_targets(ice->blitter, ice->state.so_targets, 447ec681f3Smrg (struct pipe_stream_output_target**)ice->state.so_target); 457ec681f3Smrg util_blitter_save_vertex_buffer_slot(ice->blitter, ice->state.vertex_buffers); 467ec681f3Smrg util_blitter_save_vertex_elements(ice->blitter, (void *)ice->state.cso_vertex_elements); 477ec681f3Smrg if (op & CROCUS_SAVE_FRAGMENT_STATE) { 487ec681f3Smrg util_blitter_save_blend(ice->blitter, ice->state.cso_blend); 497ec681f3Smrg util_blitter_save_depth_stencil_alpha(ice->blitter, ice->state.cso_zsa); 507ec681f3Smrg util_blitter_save_stencil_ref(ice->blitter, &ice->state.stencil_ref); 517ec681f3Smrg util_blitter_save_fragment_shader(ice->blitter, ice->shaders.uncompiled[MESA_SHADER_FRAGMENT]); 527ec681f3Smrg util_blitter_save_sample_mask(ice->blitter, ice->state.sample_mask); 537ec681f3Smrg util_blitter_save_rasterizer(ice->blitter, ice->state.cso_rast); 547ec681f3Smrg util_blitter_save_scissor(ice->blitter, &ice->state.scissors[0]); 557ec681f3Smrg util_blitter_save_viewport(ice->blitter, &ice->state.viewports[0]); 567ec681f3Smrg util_blitter_save_fragment_constant_buffer_slot(ice->blitter, &ice->state.shaders[MESA_SHADER_FRAGMENT].constbufs[0]); 577ec681f3Smrg } 587ec681f3Smrg 597ec681f3Smrg if (!render_cond) 607ec681f3Smrg util_blitter_save_render_condition(ice->blitter, 617ec681f3Smrg (struct pipe_query *)ice->condition.query, 627ec681f3Smrg ice->condition.condition, 637ec681f3Smrg ice->condition.mode); 647ec681f3Smrg 657ec681f3Smrg// util_blitter_save_scissor(ice->blitter, &ice->scissors[0]); 667ec681f3Smrg if (op & CROCUS_SAVE_FRAMEBUFFER) 677ec681f3Smrg util_blitter_save_framebuffer(ice->blitter, &ice->state.framebuffer); 687ec681f3Smrg 697ec681f3Smrg if (op & CROCUS_SAVE_TEXTURES) { 707ec681f3Smrg util_blitter_save_fragment_sampler_states(ice->blitter, 1, (void **)ice->state.shaders[MESA_SHADER_FRAGMENT].samplers); 717ec681f3Smrg util_blitter_save_fragment_sampler_views(ice->blitter, 1, (struct pipe_sampler_view **)ice->state.shaders[MESA_SHADER_FRAGMENT].textures); 727ec681f3Smrg } 737ec681f3Smrg} 747ec681f3Smrg 757ec681f3Smrg/** 767ec681f3Smrg * Helper function for handling mirror image blits. 777ec681f3Smrg * 787ec681f3Smrg * If coord0 > coord1, swap them and return "true" (mirrored). 797ec681f3Smrg */ 807ec681f3Smrgstatic bool 817ec681f3Smrgapply_mirror(float *coord0, float *coord1) 827ec681f3Smrg{ 837ec681f3Smrg if (*coord0 > *coord1) { 847ec681f3Smrg float tmp = *coord0; 857ec681f3Smrg *coord0 = *coord1; 867ec681f3Smrg *coord1 = tmp; 877ec681f3Smrg return true; 887ec681f3Smrg } 897ec681f3Smrg return false; 907ec681f3Smrg} 917ec681f3Smrg 927ec681f3Smrg/** 937ec681f3Smrg * Compute the number of pixels to clip for each side of a rect 947ec681f3Smrg * 957ec681f3Smrg * \param x0 The rect's left coordinate 967ec681f3Smrg * \param y0 The rect's bottom coordinate 977ec681f3Smrg * \param x1 The rect's right coordinate 987ec681f3Smrg * \param y1 The rect's top coordinate 997ec681f3Smrg * \param min_x The clipping region's left coordinate 1007ec681f3Smrg * \param min_y The clipping region's bottom coordinate 1017ec681f3Smrg * \param max_x The clipping region's right coordinate 1027ec681f3Smrg * \param max_y The clipping region's top coordinate 1037ec681f3Smrg * \param clipped_x0 The number of pixels to clip from the left side 1047ec681f3Smrg * \param clipped_y0 The number of pixels to clip from the bottom side 1057ec681f3Smrg * \param clipped_x1 The number of pixels to clip from the right side 1067ec681f3Smrg * \param clipped_y1 The number of pixels to clip from the top side 1077ec681f3Smrg * 1087ec681f3Smrg * \return false if we clip everything away, true otherwise 1097ec681f3Smrg */ 1107ec681f3Smrgstatic inline bool 1117ec681f3Smrgcompute_pixels_clipped(float x0, float y0, float x1, float y1, 1127ec681f3Smrg float min_x, float min_y, float max_x, float max_y, 1137ec681f3Smrg float *clipped_x0, float *clipped_y0, 1147ec681f3Smrg float *clipped_x1, float *clipped_y1) 1157ec681f3Smrg{ 1167ec681f3Smrg /* If we are going to clip everything away, stop. */ 1177ec681f3Smrg if (!(min_x <= max_x && 1187ec681f3Smrg min_y <= max_y && 1197ec681f3Smrg x0 <= max_x && 1207ec681f3Smrg y0 <= max_y && 1217ec681f3Smrg min_x <= x1 && 1227ec681f3Smrg min_y <= y1 && 1237ec681f3Smrg x0 <= x1 && 1247ec681f3Smrg y0 <= y1)) { 1257ec681f3Smrg return false; 1267ec681f3Smrg } 1277ec681f3Smrg 1287ec681f3Smrg if (x0 < min_x) 1297ec681f3Smrg *clipped_x0 = min_x - x0; 1307ec681f3Smrg else 1317ec681f3Smrg *clipped_x0 = 0; 1327ec681f3Smrg if (max_x < x1) 1337ec681f3Smrg *clipped_x1 = x1 - max_x; 1347ec681f3Smrg else 1357ec681f3Smrg *clipped_x1 = 0; 1367ec681f3Smrg 1377ec681f3Smrg if (y0 < min_y) 1387ec681f3Smrg *clipped_y0 = min_y - y0; 1397ec681f3Smrg else 1407ec681f3Smrg *clipped_y0 = 0; 1417ec681f3Smrg if (max_y < y1) 1427ec681f3Smrg *clipped_y1 = y1 - max_y; 1437ec681f3Smrg else 1447ec681f3Smrg *clipped_y1 = 0; 1457ec681f3Smrg 1467ec681f3Smrg return true; 1477ec681f3Smrg} 1487ec681f3Smrg 1497ec681f3Smrg/** 1507ec681f3Smrg * Clips a coordinate (left, right, top or bottom) for the src or dst rect 1517ec681f3Smrg * (whichever requires the largest clip) and adjusts the coordinate 1527ec681f3Smrg * for the other rect accordingly. 1537ec681f3Smrg * 1547ec681f3Smrg * \param mirror true if mirroring is required 1557ec681f3Smrg * \param src the source rect coordinate (for example src_x0) 1567ec681f3Smrg * \param dst0 the dst rect coordinate (for example dst_x0) 1577ec681f3Smrg * \param dst1 the opposite dst rect coordinate (for example dst_x1) 1587ec681f3Smrg * \param clipped_dst0 number of pixels to clip from the dst coordinate 1597ec681f3Smrg * \param clipped_dst1 number of pixels to clip from the opposite dst coordinate 1607ec681f3Smrg * \param scale the src vs dst scale involved for that coordinate 1617ec681f3Smrg * \param is_left_or_bottom true if we are clipping the left or bottom sides 1627ec681f3Smrg * of the rect. 1637ec681f3Smrg */ 1647ec681f3Smrgstatic void 1657ec681f3Smrgclip_coordinates(bool mirror, 1667ec681f3Smrg float *src, float *dst0, float *dst1, 1677ec681f3Smrg float clipped_dst0, 1687ec681f3Smrg float clipped_dst1, 1697ec681f3Smrg float scale, 1707ec681f3Smrg bool is_left_or_bottom) 1717ec681f3Smrg{ 1727ec681f3Smrg /* When clipping we need to add or subtract pixels from the original 1737ec681f3Smrg * coordinates depending on whether we are acting on the left/bottom 1747ec681f3Smrg * or right/top sides of the rect respectively. We assume we have to 1757ec681f3Smrg * add them in the code below, and multiply by -1 when we should 1767ec681f3Smrg * subtract. 1777ec681f3Smrg */ 1787ec681f3Smrg int mult = is_left_or_bottom ? 1 : -1; 1797ec681f3Smrg 1807ec681f3Smrg if (!mirror) { 1817ec681f3Smrg *dst0 += clipped_dst0 * mult; 1827ec681f3Smrg *src += clipped_dst0 * scale * mult; 1837ec681f3Smrg } else { 1847ec681f3Smrg *dst1 -= clipped_dst1 * mult; 1857ec681f3Smrg *src += clipped_dst1 * scale * mult; 1867ec681f3Smrg } 1877ec681f3Smrg} 1887ec681f3Smrg 1897ec681f3Smrg/** 1907ec681f3Smrg * Apply a scissor rectangle to blit coordinates. 1917ec681f3Smrg * 1927ec681f3Smrg * Returns true if the blit was entirely scissored away. 1937ec681f3Smrg */ 1947ec681f3Smrgstatic bool 1957ec681f3Smrgapply_blit_scissor(const struct pipe_scissor_state *scissor, 1967ec681f3Smrg float *src_x0, float *src_y0, 1977ec681f3Smrg float *src_x1, float *src_y1, 1987ec681f3Smrg float *dst_x0, float *dst_y0, 1997ec681f3Smrg float *dst_x1, float *dst_y1, 2007ec681f3Smrg bool mirror_x, bool mirror_y) 2017ec681f3Smrg{ 2027ec681f3Smrg float clip_dst_x0, clip_dst_x1, clip_dst_y0, clip_dst_y1; 2037ec681f3Smrg 2047ec681f3Smrg /* Compute number of pixels to scissor away. */ 2057ec681f3Smrg if (!compute_pixels_clipped(*dst_x0, *dst_y0, *dst_x1, *dst_y1, 2067ec681f3Smrg scissor->minx, scissor->miny, 2077ec681f3Smrg scissor->maxx, scissor->maxy, 2087ec681f3Smrg &clip_dst_x0, &clip_dst_y0, 2097ec681f3Smrg &clip_dst_x1, &clip_dst_y1)) 2107ec681f3Smrg return true; 2117ec681f3Smrg 2127ec681f3Smrg // XXX: comments assume source clipping, which we don't do 2137ec681f3Smrg 2147ec681f3Smrg /* When clipping any of the two rects we need to adjust the coordinates 2157ec681f3Smrg * in the other rect considering the scaling factor involved. To obtain 2167ec681f3Smrg * the best precision we want to make sure that we only clip once per 2177ec681f3Smrg * side to avoid accumulating errors due to the scaling adjustment. 2187ec681f3Smrg * 2197ec681f3Smrg * For example, if src_x0 and dst_x0 need both to be clipped we want to 2207ec681f3Smrg * avoid the situation where we clip src_x0 first, then adjust dst_x0 2217ec681f3Smrg * accordingly but then we realize that the resulting dst_x0 still needs 2227ec681f3Smrg * to be clipped, so we clip dst_x0 and adjust src_x0 again. Because we are 2237ec681f3Smrg * applying scaling factors to adjust the coordinates in each clipping 2247ec681f3Smrg * pass we lose some precision and that can affect the results of the 2257ec681f3Smrg * blorp blit operation slightly. What we want to do here is detect the 2267ec681f3Smrg * rect that we should clip first for each side so that when we adjust 2277ec681f3Smrg * the other rect we ensure the resulting coordinate does not need to be 2287ec681f3Smrg * clipped again. 2297ec681f3Smrg * 2307ec681f3Smrg * The code below implements this by comparing the number of pixels that 2317ec681f3Smrg * we need to clip for each side of both rects considering the scales 2327ec681f3Smrg * involved. For example, clip_src_x0 represents the number of pixels 2337ec681f3Smrg * to be clipped for the src rect's left side, so if clip_src_x0 = 5, 2347ec681f3Smrg * clip_dst_x0 = 4 and scale_x = 2 it means that we are clipping more 2357ec681f3Smrg * from the dst rect so we should clip dst_x0 only and adjust src_x0. 2367ec681f3Smrg * This is because clipping 4 pixels in the dst is equivalent to 2377ec681f3Smrg * clipping 4 * 2 = 8 > 5 in the src. 2387ec681f3Smrg */ 2397ec681f3Smrg 2407ec681f3Smrg if (*src_x0 == *src_x1 || *src_y0 == *src_y1 2417ec681f3Smrg || *dst_x0 == *dst_x1 || *dst_y0 == *dst_y1) 2427ec681f3Smrg return true; 2437ec681f3Smrg 2447ec681f3Smrg float scale_x = (float) (*src_x1 - *src_x0) / (*dst_x1 - *dst_x0); 2457ec681f3Smrg float scale_y = (float) (*src_y1 - *src_y0) / (*dst_y1 - *dst_y0); 2467ec681f3Smrg 2477ec681f3Smrg /* Clip left side */ 2487ec681f3Smrg clip_coordinates(mirror_x, src_x0, dst_x0, dst_x1, 2497ec681f3Smrg clip_dst_x0, clip_dst_x1, scale_x, true); 2507ec681f3Smrg 2517ec681f3Smrg /* Clip right side */ 2527ec681f3Smrg clip_coordinates(mirror_x, src_x1, dst_x1, dst_x0, 2537ec681f3Smrg clip_dst_x1, clip_dst_x0, scale_x, false); 2547ec681f3Smrg 2557ec681f3Smrg /* Clip bottom side */ 2567ec681f3Smrg clip_coordinates(mirror_y, src_y0, dst_y0, dst_y1, 2577ec681f3Smrg clip_dst_y0, clip_dst_y1, scale_y, true); 2587ec681f3Smrg 2597ec681f3Smrg /* Clip top side */ 2607ec681f3Smrg clip_coordinates(mirror_y, src_y1, dst_y1, dst_y0, 2617ec681f3Smrg clip_dst_y1, clip_dst_y0, scale_y, false); 2627ec681f3Smrg 2637ec681f3Smrg /* Check for invalid bounds 2647ec681f3Smrg * Can't blit for 0-dimensions 2657ec681f3Smrg */ 2667ec681f3Smrg return *src_x0 == *src_x1 || *src_y0 == *src_y1 2677ec681f3Smrg || *dst_x0 == *dst_x1 || *dst_y0 == *dst_y1; 2687ec681f3Smrg} 2697ec681f3Smrg 2707ec681f3Smrgvoid 2717ec681f3Smrgcrocus_blorp_surf_for_resource(struct crocus_vtable *vtbl, 2727ec681f3Smrg struct isl_device *isl_dev, 2737ec681f3Smrg struct blorp_surf *surf, 2747ec681f3Smrg struct pipe_resource *p_res, 2757ec681f3Smrg enum isl_aux_usage aux_usage, 2767ec681f3Smrg unsigned level, 2777ec681f3Smrg bool is_render_target) 2787ec681f3Smrg{ 2797ec681f3Smrg struct crocus_resource *res = (void *) p_res; 2807ec681f3Smrg 2817ec681f3Smrg assert(!crocus_resource_unfinished_aux_import(res)); 2827ec681f3Smrg 2837ec681f3Smrg if (isl_aux_usage_has_hiz(aux_usage) && 2847ec681f3Smrg !crocus_resource_level_has_hiz(res, level)) 2857ec681f3Smrg aux_usage = ISL_AUX_USAGE_NONE; 2867ec681f3Smrg 2877ec681f3Smrg *surf = (struct blorp_surf) { 2887ec681f3Smrg .surf = &res->surf, 2897ec681f3Smrg .addr = (struct blorp_address) { 2907ec681f3Smrg .buffer = res->bo, 2917ec681f3Smrg .offset = res->offset, 2927ec681f3Smrg .reloc_flags = is_render_target ? EXEC_OBJECT_WRITE : 0, 2937ec681f3Smrg .mocs = crocus_mocs(res->bo, isl_dev), 2947ec681f3Smrg }, 2957ec681f3Smrg .aux_usage = aux_usage, 2967ec681f3Smrg }; 2977ec681f3Smrg 2987ec681f3Smrg if (aux_usage != ISL_AUX_USAGE_NONE) { 2997ec681f3Smrg surf->aux_surf = &res->aux.surf; 3007ec681f3Smrg surf->aux_addr = (struct blorp_address) { 3017ec681f3Smrg .buffer = res->aux.bo, 3027ec681f3Smrg .offset = res->aux.offset, 3037ec681f3Smrg .reloc_flags = is_render_target ? EXEC_OBJECT_WRITE : 0, 3047ec681f3Smrg .mocs = crocus_mocs(res->bo, isl_dev), 3057ec681f3Smrg }; 3067ec681f3Smrg surf->clear_color = 3077ec681f3Smrg crocus_resource_get_clear_color(res); 3087ec681f3Smrg } 3097ec681f3Smrg} 3107ec681f3Smrg 3117ec681f3Smrgstatic void 3127ec681f3Smrgtex_cache_flush_hack(struct crocus_batch *batch, 3137ec681f3Smrg enum isl_format view_format, 3147ec681f3Smrg enum isl_format surf_format) 3157ec681f3Smrg{ 3167ec681f3Smrg /* The WaSamplerCacheFlushBetweenRedescribedSurfaceReads workaround says: 3177ec681f3Smrg * 3187ec681f3Smrg * "Currently Sampler assumes that a surface would not have two 3197ec681f3Smrg * different format associate with it. It will not properly cache 3207ec681f3Smrg * the different views in the MT cache, causing a data corruption." 3217ec681f3Smrg * 3227ec681f3Smrg * We may need to handle this for texture views in general someday, but 3237ec681f3Smrg * for now we handle it here, as it hurts copies and blits particularly 3247ec681f3Smrg * badly because they ofter reinterpret formats. 3257ec681f3Smrg * 3267ec681f3Smrg * If the BO hasn't been referenced yet this batch, we assume that the 3277ec681f3Smrg * texture cache doesn't contain any relevant data nor need flushing. 3287ec681f3Smrg * 3297ec681f3Smrg * Icelake (Gen11+) claims to fix this issue, but seems to still have 3307ec681f3Smrg * issues with ASTC formats. 3317ec681f3Smrg */ 3327ec681f3Smrg bool need_flush = view_format != surf_format; 3337ec681f3Smrg if (!need_flush) 3347ec681f3Smrg return; 3357ec681f3Smrg 3367ec681f3Smrg const char *reason = 3377ec681f3Smrg "workaround: WaSamplerCacheFlushBetweenRedescribedSurfaceReads"; 3387ec681f3Smrg 3397ec681f3Smrg crocus_emit_pipe_control_flush(batch, reason, PIPE_CONTROL_CS_STALL); 3407ec681f3Smrg crocus_emit_pipe_control_flush(batch, reason, 3417ec681f3Smrg PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE); 3427ec681f3Smrg} 3437ec681f3Smrg 3447ec681f3Smrgstatic struct crocus_resource * 3457ec681f3Smrgcrocus_resource_for_aspect(const struct intel_device_info *devinfo, 3467ec681f3Smrg struct pipe_resource *p_res, unsigned pipe_mask) 3477ec681f3Smrg{ 3487ec681f3Smrg if (pipe_mask == PIPE_MASK_S) { 3497ec681f3Smrg struct crocus_resource *junk, *s_res; 3507ec681f3Smrg crocus_get_depth_stencil_resources(devinfo, p_res, &junk, &s_res); 3517ec681f3Smrg return s_res; 3527ec681f3Smrg } else { 3537ec681f3Smrg return (struct crocus_resource *)p_res; 3547ec681f3Smrg } 3557ec681f3Smrg} 3567ec681f3Smrg 3577ec681f3Smrgstatic enum pipe_format 3587ec681f3Smrgpipe_format_for_aspect(enum pipe_format format, unsigned pipe_mask) 3597ec681f3Smrg{ 3607ec681f3Smrg if (pipe_mask == PIPE_MASK_S) { 3617ec681f3Smrg return util_format_stencil_only(format); 3627ec681f3Smrg } else if (pipe_mask == PIPE_MASK_Z) { 3637ec681f3Smrg return util_format_get_depth_only(format); 3647ec681f3Smrg } else { 3657ec681f3Smrg return format; 3667ec681f3Smrg } 3677ec681f3Smrg} 3687ec681f3Smrg 3697ec681f3Smrgstatic void 3707ec681f3Smrgcrocus_u_blitter(struct crocus_context *ice, 3717ec681f3Smrg const struct pipe_blit_info *info) 3727ec681f3Smrg{ 3737ec681f3Smrg struct pipe_blit_info dinfo = *info; 3747ec681f3Smrg if (!util_format_has_alpha(dinfo.dst.resource->format)) 3757ec681f3Smrg dinfo.mask &= ~PIPE_MASK_A; 3767ec681f3Smrg crocus_blitter_begin(ice, CROCUS_SAVE_FRAMEBUFFER | CROCUS_SAVE_TEXTURES | CROCUS_SAVE_FRAGMENT_STATE, info->render_condition_enable); 3777ec681f3Smrg util_blitter_blit(ice->blitter, &dinfo); 3787ec681f3Smrg} 3797ec681f3Smrg 3807ec681f3Smrg/** 3817ec681f3Smrg * The pipe->blit() driver hook. 3827ec681f3Smrg * 3837ec681f3Smrg * This performs a blit between two surfaces, which copies data but may 3847ec681f3Smrg * also perform format conversion, scaling, flipping, and so on. 3857ec681f3Smrg */ 3867ec681f3Smrgstatic void 3877ec681f3Smrgcrocus_blit(struct pipe_context *ctx, const struct pipe_blit_info *info) 3887ec681f3Smrg{ 3897ec681f3Smrg struct crocus_context *ice = (void *) ctx; 3907ec681f3Smrg struct crocus_screen *screen = (struct crocus_screen *)ctx->screen; 3917ec681f3Smrg const struct intel_device_info *devinfo = &screen->devinfo; 3927ec681f3Smrg struct crocus_batch *batch = &ice->batches[CROCUS_BATCH_RENDER]; 3937ec681f3Smrg enum blorp_batch_flags blorp_flags = 0; 3947ec681f3Smrg 3957ec681f3Smrg /* We don't support color masking. */ 3967ec681f3Smrg assert((info->mask & PIPE_MASK_RGBA) == PIPE_MASK_RGBA || 3977ec681f3Smrg (info->mask & PIPE_MASK_RGBA) == 0); 3987ec681f3Smrg 3997ec681f3Smrg if (info->render_condition_enable) 4007ec681f3Smrg if (!crocus_check_conditional_render(ice)) 4017ec681f3Smrg return; 4027ec681f3Smrg 4037ec681f3Smrg if (devinfo->ver <= 5) { 4047ec681f3Smrg if (!screen->vtbl.blit_blt(batch, info)) { 4057ec681f3Smrg 4067ec681f3Smrg if (!util_format_is_depth_or_stencil(info->src.resource->format) && 4077ec681f3Smrg info->dst.resource->target != PIPE_TEXTURE_3D) 4087ec681f3Smrg goto use_blorp; 4097ec681f3Smrg 4107ec681f3Smrg if (!util_blitter_is_blit_supported(ice->blitter, info)) { 4117ec681f3Smrg if (util_format_is_depth_or_stencil(info->src.resource->format)) { 4127ec681f3Smrg 4137ec681f3Smrg struct pipe_blit_info depth_blit = *info; 4147ec681f3Smrg depth_blit.mask = PIPE_MASK_Z; 4157ec681f3Smrg crocus_blitter_begin(ice, CROCUS_SAVE_FRAMEBUFFER | CROCUS_SAVE_TEXTURES | CROCUS_SAVE_FRAGMENT_STATE, info->render_condition_enable); 4167ec681f3Smrg util_blitter_blit(ice->blitter, &depth_blit); 4177ec681f3Smrg 4187ec681f3Smrg struct pipe_surface *dst_view, dst_templ; 4197ec681f3Smrg util_blitter_default_dst_texture(&dst_templ, info->dst.resource, info->dst.level, info->dst.box.z); 4207ec681f3Smrg dst_view = ctx->create_surface(ctx, info->dst.resource, &dst_templ); 4217ec681f3Smrg 4227ec681f3Smrg crocus_blitter_begin(ice, CROCUS_SAVE_FRAMEBUFFER | CROCUS_SAVE_TEXTURES | CROCUS_SAVE_FRAGMENT_STATE, info->render_condition_enable); 4237ec681f3Smrg 4247ec681f3Smrg util_blitter_clear_depth_stencil(ice->blitter, dst_view, PIPE_CLEAR_STENCIL, 4257ec681f3Smrg 0, 0, info->dst.box.x, info->dst.box.y, 4267ec681f3Smrg info->dst.box.width, info->dst.box.height); 4277ec681f3Smrg crocus_blitter_begin(ice, CROCUS_SAVE_FRAMEBUFFER | CROCUS_SAVE_TEXTURES | CROCUS_SAVE_FRAGMENT_STATE, info->render_condition_enable); 4287ec681f3Smrg util_blitter_stencil_fallback(ice->blitter, 4297ec681f3Smrg info->dst.resource, 4307ec681f3Smrg info->dst.level, 4317ec681f3Smrg &info->dst.box, 4327ec681f3Smrg info->src.resource, 4337ec681f3Smrg info->src.level, 4347ec681f3Smrg &info->src.box, NULL); 4357ec681f3Smrg 4367ec681f3Smrg pipe_surface_release(ctx, &dst_view); 4377ec681f3Smrg } 4387ec681f3Smrg return; 4397ec681f3Smrg } 4407ec681f3Smrg 4417ec681f3Smrg crocus_u_blitter(ice, info); 4427ec681f3Smrg } 4437ec681f3Smrg return; 4447ec681f3Smrg } 4457ec681f3Smrg 4467ec681f3Smrg if (devinfo->ver == 6) { 4477ec681f3Smrg if (info->src.resource->target == PIPE_TEXTURE_3D && 4487ec681f3Smrg info->dst.resource->target == PIPE_TEXTURE_3D) { 4497ec681f3Smrg crocus_u_blitter(ice, info); 4507ec681f3Smrg return; 4517ec681f3Smrg } 4527ec681f3Smrg } 4537ec681f3Smrg 4547ec681f3Smrguse_blorp: 4557ec681f3Smrg if (info->render_condition_enable) { 4567ec681f3Smrg if (ice->state.predicate == CROCUS_PREDICATE_STATE_USE_BIT) 4577ec681f3Smrg blorp_flags |= BLORP_BATCH_PREDICATE_ENABLE; 4587ec681f3Smrg } 4597ec681f3Smrg 4607ec681f3Smrg float src_x0 = info->src.box.x; 4617ec681f3Smrg float src_x1 = info->src.box.x + info->src.box.width; 4627ec681f3Smrg float src_y0 = info->src.box.y; 4637ec681f3Smrg float src_y1 = info->src.box.y + info->src.box.height; 4647ec681f3Smrg float dst_x0 = info->dst.box.x; 4657ec681f3Smrg float dst_x1 = info->dst.box.x + info->dst.box.width; 4667ec681f3Smrg float dst_y0 = info->dst.box.y; 4677ec681f3Smrg float dst_y1 = info->dst.box.y + info->dst.box.height; 4687ec681f3Smrg bool mirror_x = apply_mirror(&src_x0, &src_x1); 4697ec681f3Smrg bool mirror_y = apply_mirror(&src_y0, &src_y1); 4707ec681f3Smrg enum blorp_filter filter; 4717ec681f3Smrg 4727ec681f3Smrg if (info->scissor_enable) { 4737ec681f3Smrg bool noop = apply_blit_scissor(&info->scissor, 4747ec681f3Smrg &src_x0, &src_y0, &src_x1, &src_y1, 4757ec681f3Smrg &dst_x0, &dst_y0, &dst_x1, &dst_y1, 4767ec681f3Smrg mirror_x, mirror_y); 4777ec681f3Smrg if (noop) 4787ec681f3Smrg return; 4797ec681f3Smrg } 4807ec681f3Smrg 4817ec681f3Smrg if (abs(info->dst.box.width) == abs(info->src.box.width) && 4827ec681f3Smrg abs(info->dst.box.height) == abs(info->src.box.height)) { 4837ec681f3Smrg if (info->src.resource->nr_samples > 1 && 4847ec681f3Smrg info->dst.resource->nr_samples <= 1) { 4857ec681f3Smrg /* The OpenGL ES 3.2 specification, section 16.2.1, says: 4867ec681f3Smrg * 4877ec681f3Smrg * "If the read framebuffer is multisampled (its effective 4887ec681f3Smrg * value of SAMPLE_BUFFERS is one) and the draw framebuffer 4897ec681f3Smrg * is not (its value of SAMPLE_BUFFERS is zero), the samples 4907ec681f3Smrg * corresponding to each pixel location in the source are 4917ec681f3Smrg * converted to a single sample before being written to the 4927ec681f3Smrg * destination. The filter parameter is ignored. If the 4937ec681f3Smrg * source formats are integer types or stencil values, a 4947ec681f3Smrg * single sample’s value is selected for each pixel. If the 4957ec681f3Smrg * source formats are floating-point or normalized types, 4967ec681f3Smrg * the sample values for each pixel are resolved in an 4977ec681f3Smrg * implementation-dependent manner. If the source formats 4987ec681f3Smrg * are depth values, sample values are resolved in an 4997ec681f3Smrg * implementation-dependent manner where the result will be 5007ec681f3Smrg * between the minimum and maximum depth values in the pixel." 5017ec681f3Smrg * 5027ec681f3Smrg * When selecting a single sample, we always choose sample 0. 5037ec681f3Smrg */ 5047ec681f3Smrg if (util_format_is_depth_or_stencil(info->src.format) || 5057ec681f3Smrg util_format_is_pure_integer(info->src.format)) { 5067ec681f3Smrg filter = BLORP_FILTER_SAMPLE_0; 5077ec681f3Smrg } else { 5087ec681f3Smrg filter = BLORP_FILTER_AVERAGE; 5097ec681f3Smrg } 5107ec681f3Smrg } else { 5117ec681f3Smrg /* The OpenGL 4.6 specification, section 18.3.1, says: 5127ec681f3Smrg * 5137ec681f3Smrg * "If the source and destination dimensions are identical, 5147ec681f3Smrg * no filtering is applied." 5157ec681f3Smrg * 5167ec681f3Smrg * Using BLORP_FILTER_NONE will also handle the upsample case by 5177ec681f3Smrg * replicating the one value in the source to all values in the 5187ec681f3Smrg * destination. 5197ec681f3Smrg */ 5207ec681f3Smrg filter = BLORP_FILTER_NONE; 5217ec681f3Smrg } 5227ec681f3Smrg } else if (info->filter == PIPE_TEX_FILTER_LINEAR) { 5237ec681f3Smrg filter = BLORP_FILTER_BILINEAR; 5247ec681f3Smrg } else { 5257ec681f3Smrg filter = BLORP_FILTER_NEAREST; 5267ec681f3Smrg } 5277ec681f3Smrg 5287ec681f3Smrg struct blorp_batch blorp_batch; 5297ec681f3Smrg blorp_batch_init(&ice->blorp, &blorp_batch, batch, blorp_flags); 5307ec681f3Smrg 5317ec681f3Smrg float src_z_step = (float)info->src.box.depth / (float)info->dst.box.depth; 5327ec681f3Smrg 5337ec681f3Smrg /* There is no interpolation to the pixel center during rendering, so 5347ec681f3Smrg * add the 0.5 offset ourselves here. 5357ec681f3Smrg */ 5367ec681f3Smrg float depth_center_offset = 0; 5377ec681f3Smrg if (info->src.resource->target == PIPE_TEXTURE_3D) 5387ec681f3Smrg depth_center_offset = 0.5 / info->dst.box.depth * info->src.box.depth; 5397ec681f3Smrg 5407ec681f3Smrg /* Perform a blit for each aspect requested by the caller. PIPE_MASK_R is 5417ec681f3Smrg * used to represent the color aspect. */ 5427ec681f3Smrg unsigned aspect_mask = info->mask & (PIPE_MASK_R | PIPE_MASK_ZS); 5437ec681f3Smrg while (aspect_mask) { 5447ec681f3Smrg unsigned aspect = 1 << u_bit_scan(&aspect_mask); 5457ec681f3Smrg 5467ec681f3Smrg struct crocus_resource *src_res = 5477ec681f3Smrg crocus_resource_for_aspect(devinfo, info->src.resource, aspect); 5487ec681f3Smrg struct crocus_resource *dst_res = 5497ec681f3Smrg crocus_resource_for_aspect(devinfo, info->dst.resource, aspect); 5507ec681f3Smrg 5517ec681f3Smrg enum pipe_format src_pfmt = 5527ec681f3Smrg pipe_format_for_aspect(info->src.format, aspect); 5537ec681f3Smrg enum pipe_format dst_pfmt = 5547ec681f3Smrg pipe_format_for_aspect(info->dst.format, aspect); 5557ec681f3Smrg 5567ec681f3Smrg if (crocus_resource_unfinished_aux_import(src_res)) 5577ec681f3Smrg crocus_resource_finish_aux_import(ctx->screen, src_res); 5587ec681f3Smrg if (crocus_resource_unfinished_aux_import(dst_res)) 5597ec681f3Smrg crocus_resource_finish_aux_import(ctx->screen, dst_res); 5607ec681f3Smrg 5617ec681f3Smrg struct crocus_format_info src_fmt = 5627ec681f3Smrg crocus_format_for_usage(devinfo, src_pfmt, ISL_SURF_USAGE_TEXTURE_BIT); 5637ec681f3Smrg enum isl_aux_usage src_aux_usage = 5647ec681f3Smrg crocus_resource_texture_aux_usage(src_res); 5657ec681f3Smrg 5667ec681f3Smrg crocus_resource_prepare_texture(ice, src_res, src_fmt.fmt, 5677ec681f3Smrg info->src.level, 1, info->src.box.z, 5687ec681f3Smrg info->src.box.depth); 5697ec681f3Smrg // crocus_emit_buffer_barrier_for(batch, src_res->bo, 5707ec681f3Smrg // CROCUS_DOMAIN_OTHER_READ); 5717ec681f3Smrg 5727ec681f3Smrg bool dst_aux_disable = false; 5737ec681f3Smrg /* on SNB blorp will use render target instead of depth 5747ec681f3Smrg * so disable HiZ. 5757ec681f3Smrg */ 5767ec681f3Smrg if (devinfo->ver <= 6 && util_format_is_depth_or_stencil(dst_pfmt)) 5777ec681f3Smrg dst_aux_disable = true; 5787ec681f3Smrg struct crocus_format_info dst_fmt = 5797ec681f3Smrg crocus_format_for_usage(devinfo, dst_pfmt, 5807ec681f3Smrg ISL_SURF_USAGE_RENDER_TARGET_BIT); 5817ec681f3Smrg enum isl_aux_usage dst_aux_usage = 5827ec681f3Smrg crocus_resource_render_aux_usage(ice, dst_res, info->dst.level, 5837ec681f3Smrg dst_fmt.fmt, dst_aux_disable); 5847ec681f3Smrg 5857ec681f3Smrg struct blorp_surf src_surf, dst_surf; 5867ec681f3Smrg crocus_blorp_surf_for_resource(&screen->vtbl, &screen->isl_dev, &src_surf, 5877ec681f3Smrg &src_res->base.b, src_aux_usage, 5887ec681f3Smrg info->src.level, false); 5897ec681f3Smrg crocus_blorp_surf_for_resource(&screen->vtbl, &screen->isl_dev, &dst_surf, 5907ec681f3Smrg &dst_res->base.b, dst_aux_usage, 5917ec681f3Smrg info->dst.level, true); 5927ec681f3Smrg 5937ec681f3Smrg crocus_resource_prepare_render(ice, dst_res, info->dst.level, 5947ec681f3Smrg info->dst.box.z, info->dst.box.depth, 5957ec681f3Smrg dst_aux_usage); 5967ec681f3Smrg // crocus_emit_buffer_barrier_for(batch, dst_res->bo, 5977ec681f3Smrg // CROCUS_DOMAIN_RENDER_WRITE); 5987ec681f3Smrg 5997ec681f3Smrg if (crocus_batch_references(batch, src_res->bo)) 6007ec681f3Smrg tex_cache_flush_hack(batch, src_fmt.fmt, src_res->surf.format); 6017ec681f3Smrg 6027ec681f3Smrg if (dst_res->base.b.target == PIPE_BUFFER) { 6037ec681f3Smrg util_range_add(&dst_res->base.b, &dst_res->valid_buffer_range, 6047ec681f3Smrg dst_x0, dst_x1); 6057ec681f3Smrg } 6067ec681f3Smrg 6077ec681f3Smrg struct isl_swizzle src_swiz = pipe_to_isl_swizzles(src_fmt.swizzles); 6087ec681f3Smrg struct isl_swizzle dst_swiz = pipe_to_isl_swizzles(dst_fmt.swizzles); 6097ec681f3Smrg 6107ec681f3Smrg for (int slice = 0; slice < info->dst.box.depth; slice++) { 6117ec681f3Smrg unsigned dst_z = info->dst.box.z + slice; 6127ec681f3Smrg float src_z = info->src.box.z + slice * src_z_step + 6137ec681f3Smrg depth_center_offset; 6147ec681f3Smrg 6157ec681f3Smrg crocus_batch_maybe_flush(batch, 1500); 6167ec681f3Smrg 6177ec681f3Smrg blorp_blit(&blorp_batch, 6187ec681f3Smrg &src_surf, info->src.level, src_z, 6197ec681f3Smrg src_fmt.fmt, src_swiz, 6207ec681f3Smrg &dst_surf, info->dst.level, dst_z, 6217ec681f3Smrg dst_fmt.fmt, dst_swiz, 6227ec681f3Smrg src_x0, src_y0, src_x1, src_y1, 6237ec681f3Smrg dst_x0, dst_y0, dst_x1, dst_y1, 6247ec681f3Smrg filter, mirror_x, mirror_y); 6257ec681f3Smrg 6267ec681f3Smrg } 6277ec681f3Smrg 6287ec681f3Smrg tex_cache_flush_hack(batch, src_fmt.fmt, src_res->surf.format); 6297ec681f3Smrg 6307ec681f3Smrg crocus_resource_finish_render(ice, dst_res, info->dst.level, 6317ec681f3Smrg info->dst.box.z, info->dst.box.depth, 6327ec681f3Smrg dst_aux_usage); 6337ec681f3Smrg } 6347ec681f3Smrg 6357ec681f3Smrg blorp_batch_finish(&blorp_batch); 6367ec681f3Smrg 6377ec681f3Smrg crocus_flush_and_dirty_for_history(ice, batch, (struct crocus_resource *) 6387ec681f3Smrg info->dst.resource, 6397ec681f3Smrg PIPE_CONTROL_RENDER_TARGET_FLUSH, 6407ec681f3Smrg "cache history: post-blit"); 6417ec681f3Smrg} 6427ec681f3Smrg 6437ec681f3Smrgstatic void 6447ec681f3Smrgget_copy_region_aux_settings(struct crocus_resource *res, 6457ec681f3Smrg enum isl_aux_usage *out_aux_usage, 6467ec681f3Smrg bool is_render_target) 6477ec681f3Smrg{ 6487ec681f3Smrg switch (res->aux.usage) { 6497ec681f3Smrg case ISL_AUX_USAGE_MCS: 6507ec681f3Smrg /* A stencil resolve operation must be performed prior to doing resource 6517ec681f3Smrg * copies or used by CPU. 6527ec681f3Smrg * (see HSD 1209978162) 6537ec681f3Smrg */ 6547ec681f3Smrg if (is_render_target && isl_surf_usage_is_stencil(res->surf.usage)) { 6557ec681f3Smrg *out_aux_usage = ISL_AUX_USAGE_NONE; 6567ec681f3Smrg } else { 6577ec681f3Smrg *out_aux_usage = res->aux.usage; 6587ec681f3Smrg } 6597ec681f3Smrg break; 6607ec681f3Smrg default: 6617ec681f3Smrg *out_aux_usage = ISL_AUX_USAGE_NONE; 6627ec681f3Smrg break; 6637ec681f3Smrg } 6647ec681f3Smrg} 6657ec681f3Smrg 6667ec681f3Smrg/** 6677ec681f3Smrg * Perform a GPU-based raw memory copy between compatible view classes. 6687ec681f3Smrg * 6697ec681f3Smrg * Does not perform any flushing - the new data may still be left in the 6707ec681f3Smrg * render cache, and old data may remain in other caches. 6717ec681f3Smrg * 6727ec681f3Smrg * Wraps blorp_copy() and blorp_buffer_copy(). 6737ec681f3Smrg */ 6747ec681f3Smrgvoid 6757ec681f3Smrgcrocus_copy_region(struct blorp_context *blorp, 6767ec681f3Smrg struct crocus_batch *batch, 6777ec681f3Smrg struct pipe_resource *dst, 6787ec681f3Smrg unsigned dst_level, 6797ec681f3Smrg unsigned dstx, unsigned dsty, unsigned dstz, 6807ec681f3Smrg struct pipe_resource *src, 6817ec681f3Smrg unsigned src_level, 6827ec681f3Smrg const struct pipe_box *src_box) 6837ec681f3Smrg{ 6847ec681f3Smrg struct blorp_batch blorp_batch; 6857ec681f3Smrg struct crocus_context *ice = blorp->driver_ctx; 6867ec681f3Smrg struct crocus_screen *screen = (void *) ice->ctx.screen; 6877ec681f3Smrg const struct intel_device_info *devinfo = &screen->devinfo; 6887ec681f3Smrg struct crocus_resource *src_res = (void *) src; 6897ec681f3Smrg struct crocus_resource *dst_res = (void *) dst; 6907ec681f3Smrg 6917ec681f3Smrg if (devinfo->ver <= 5) { 6927ec681f3Smrg if (screen->vtbl.copy_region_blt(batch, dst_res, 6937ec681f3Smrg dst_level, dstx, dsty, dstz, 6947ec681f3Smrg src_res, src_level, src_box)) 6957ec681f3Smrg return; 6967ec681f3Smrg } 6977ec681f3Smrg enum isl_aux_usage src_aux_usage, dst_aux_usage; 6987ec681f3Smrg get_copy_region_aux_settings(src_res, &src_aux_usage, 6997ec681f3Smrg false); 7007ec681f3Smrg get_copy_region_aux_settings(dst_res, &dst_aux_usage, 7017ec681f3Smrg true); 7027ec681f3Smrg 7037ec681f3Smrg if (crocus_batch_references(batch, src_res->bo)) 7047ec681f3Smrg tex_cache_flush_hack(batch, ISL_FORMAT_UNSUPPORTED, src_res->surf.format); 7057ec681f3Smrg 7067ec681f3Smrg if (dst->target == PIPE_BUFFER) 7077ec681f3Smrg util_range_add(&dst_res->base.b, &dst_res->valid_buffer_range, dstx, dstx + src_box->width); 7087ec681f3Smrg 7097ec681f3Smrg if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) { 7107ec681f3Smrg struct blorp_address src_addr = { 7117ec681f3Smrg .buffer = crocus_resource_bo(src), .offset = src_box->x, 7127ec681f3Smrg }; 7137ec681f3Smrg struct blorp_address dst_addr = { 7147ec681f3Smrg .buffer = crocus_resource_bo(dst), .offset = dstx, 7157ec681f3Smrg .reloc_flags = EXEC_OBJECT_WRITE, 7167ec681f3Smrg }; 7177ec681f3Smrg 7187ec681f3Smrg crocus_batch_maybe_flush(batch, 1500); 7197ec681f3Smrg 7207ec681f3Smrg blorp_batch_init(&ice->blorp, &blorp_batch, batch, 0); 7217ec681f3Smrg blorp_buffer_copy(&blorp_batch, src_addr, dst_addr, src_box->width); 7227ec681f3Smrg blorp_batch_finish(&blorp_batch); 7237ec681f3Smrg } else { 7247ec681f3Smrg // XXX: what about one surface being a buffer and not the other? 7257ec681f3Smrg 7267ec681f3Smrg struct blorp_surf src_surf, dst_surf; 7277ec681f3Smrg crocus_blorp_surf_for_resource(&screen->vtbl, &screen->isl_dev, &src_surf, 7287ec681f3Smrg src, src_aux_usage, src_level, false); 7297ec681f3Smrg crocus_blorp_surf_for_resource(&screen->vtbl, &screen->isl_dev, &dst_surf, 7307ec681f3Smrg dst, dst_aux_usage, dst_level, true); 7317ec681f3Smrg 7327ec681f3Smrg crocus_resource_prepare_access(ice, src_res, src_level, 1, 7337ec681f3Smrg src_box->z, src_box->depth, 7347ec681f3Smrg src_aux_usage, false); 7357ec681f3Smrg crocus_resource_prepare_access(ice, dst_res, dst_level, 1, 7367ec681f3Smrg dstz, src_box->depth, 7377ec681f3Smrg dst_aux_usage, false); 7387ec681f3Smrg 7397ec681f3Smrg blorp_batch_init(&ice->blorp, &blorp_batch, batch, 0); 7407ec681f3Smrg 7417ec681f3Smrg for (int slice = 0; slice < src_box->depth; slice++) { 7427ec681f3Smrg crocus_batch_maybe_flush(batch, 1500); 7437ec681f3Smrg 7447ec681f3Smrg blorp_copy(&blorp_batch, &src_surf, src_level, src_box->z + slice, 7457ec681f3Smrg &dst_surf, dst_level, dstz + slice, 7467ec681f3Smrg src_box->x, src_box->y, dstx, dsty, 7477ec681f3Smrg src_box->width, src_box->height); 7487ec681f3Smrg } 7497ec681f3Smrg blorp_batch_finish(&blorp_batch); 7507ec681f3Smrg 7517ec681f3Smrg crocus_resource_finish_write(ice, dst_res, dst_level, dstz, 7527ec681f3Smrg src_box->depth, dst_aux_usage); 7537ec681f3Smrg } 7547ec681f3Smrg 7557ec681f3Smrg tex_cache_flush_hack(batch, ISL_FORMAT_UNSUPPORTED, src_res->surf.format); 7567ec681f3Smrg} 7577ec681f3Smrg 7587ec681f3Smrgstatic struct crocus_batch * 7597ec681f3Smrgget_preferred_batch(struct crocus_context *ice, struct crocus_bo *bo) 7607ec681f3Smrg{ 7617ec681f3Smrg /* If the compute batch is already using this buffer, we'd prefer to 7627ec681f3Smrg * continue queueing in the compute batch. 7637ec681f3Smrg */ 7647ec681f3Smrg if (crocus_batch_references(&ice->batches[CROCUS_BATCH_COMPUTE], bo)) 7657ec681f3Smrg return &ice->batches[CROCUS_BATCH_COMPUTE]; 7667ec681f3Smrg 7677ec681f3Smrg /* Otherwise default to the render batch. */ 7687ec681f3Smrg return &ice->batches[CROCUS_BATCH_RENDER]; 7697ec681f3Smrg} 7707ec681f3Smrg 7717ec681f3Smrg 7727ec681f3Smrg/** 7737ec681f3Smrg * The pipe->resource_copy_region() driver hook. 7747ec681f3Smrg * 7757ec681f3Smrg * This implements ARB_copy_image semantics - a raw memory copy between 7767ec681f3Smrg * compatible view classes. 7777ec681f3Smrg */ 7787ec681f3Smrgstatic void 7797ec681f3Smrgcrocus_resource_copy_region(struct pipe_context *ctx, 7807ec681f3Smrg struct pipe_resource *p_dst, 7817ec681f3Smrg unsigned dst_level, 7827ec681f3Smrg unsigned dstx, unsigned dsty, unsigned dstz, 7837ec681f3Smrg struct pipe_resource *p_src, 7847ec681f3Smrg unsigned src_level, 7857ec681f3Smrg const struct pipe_box *src_box) 7867ec681f3Smrg{ 7877ec681f3Smrg struct crocus_context *ice = (void *) ctx; 7887ec681f3Smrg struct crocus_batch *batch = &ice->batches[CROCUS_BATCH_RENDER]; 7897ec681f3Smrg struct crocus_screen *screen = (struct crocus_screen *)ctx->screen; 7907ec681f3Smrg const struct intel_device_info *devinfo = &screen->devinfo; 7917ec681f3Smrg struct crocus_resource *src = (void *) p_src; 7927ec681f3Smrg struct crocus_resource *dst = (void *) p_dst; 7937ec681f3Smrg 7947ec681f3Smrg if (crocus_resource_unfinished_aux_import(src)) 7957ec681f3Smrg crocus_resource_finish_aux_import(ctx->screen, src); 7967ec681f3Smrg if (crocus_resource_unfinished_aux_import(dst)) 7977ec681f3Smrg crocus_resource_finish_aux_import(ctx->screen, dst); 7987ec681f3Smrg 7997ec681f3Smrg /* Use MI_COPY_MEM_MEM for tiny (<= 16 byte, % 4) buffer copies. */ 8007ec681f3Smrg if (p_src->target == PIPE_BUFFER && p_dst->target == PIPE_BUFFER && 8017ec681f3Smrg (src_box->width % 4 == 0) && src_box->width <= 16 && 8027ec681f3Smrg screen->vtbl.copy_mem_mem) { 8037ec681f3Smrg struct crocus_bo *dst_bo = crocus_resource_bo(p_dst); 8047ec681f3Smrg batch = get_preferred_batch(ice, dst_bo); 8057ec681f3Smrg crocus_batch_maybe_flush(batch, 24 + 5 * (src_box->width / 4)); 8067ec681f3Smrg crocus_emit_pipe_control_flush(batch, 8077ec681f3Smrg "stall for MI_COPY_MEM_MEM copy_region", 8087ec681f3Smrg PIPE_CONTROL_CS_STALL); 8097ec681f3Smrg screen->vtbl.copy_mem_mem(batch, dst_bo, dstx, crocus_resource_bo(p_src), 8107ec681f3Smrg src_box->x, src_box->width); 8117ec681f3Smrg return; 8127ec681f3Smrg } 8137ec681f3Smrg 8147ec681f3Smrg if (devinfo->ver < 6 && util_format_is_depth_or_stencil(p_dst->format)) { 8157ec681f3Smrg util_resource_copy_region(ctx, p_dst, dst_level, dstx, dsty, dstz, 8167ec681f3Smrg p_src, src_level, src_box); 8177ec681f3Smrg return; 8187ec681f3Smrg } 8197ec681f3Smrg crocus_copy_region(&ice->blorp, batch, p_dst, dst_level, dstx, dsty, dstz, 8207ec681f3Smrg p_src, src_level, src_box); 8217ec681f3Smrg 8227ec681f3Smrg if (util_format_is_depth_and_stencil(p_dst->format) && 8237ec681f3Smrg util_format_has_stencil(util_format_description(p_src->format)) && 8247ec681f3Smrg devinfo->ver >= 6) { 8257ec681f3Smrg struct crocus_resource *junk, *s_src_res, *s_dst_res; 8267ec681f3Smrg crocus_get_depth_stencil_resources(devinfo, p_src, &junk, &s_src_res); 8277ec681f3Smrg crocus_get_depth_stencil_resources(devinfo, p_dst, &junk, &s_dst_res); 8287ec681f3Smrg 8297ec681f3Smrg crocus_copy_region(&ice->blorp, batch, &s_dst_res->base.b, dst_level, dstx, 8307ec681f3Smrg dsty, dstz, &s_src_res->base.b, src_level, src_box); 8317ec681f3Smrg } 8327ec681f3Smrg 8337ec681f3Smrg crocus_flush_and_dirty_for_history(ice, batch, dst, 8347ec681f3Smrg PIPE_CONTROL_RENDER_TARGET_FLUSH, 8357ec681f3Smrg "cache history: post copy_region"); 8367ec681f3Smrg} 8377ec681f3Smrg 8387ec681f3Smrgvoid 8397ec681f3Smrgcrocus_init_blit_functions(struct pipe_context *ctx) 8407ec681f3Smrg{ 8417ec681f3Smrg ctx->blit = crocus_blit; 8427ec681f3Smrg ctx->resource_copy_region = crocus_resource_copy_region; 8437ec681f3Smrg} 844