xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/iris/iris_resource.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2017 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included
12  * in all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20  * DEALINGS IN THE SOFTWARE.
21  */
22 
23 /**
24  * @file iris_resource.c
25  *
26  * Resources are images, buffers, and other objects used by the GPU.
27  *
28  * XXX: explain resources
29  */
30 
31 #include <stdio.h>
32 #include <errno.h>
33 #include "pipe/p_defines.h"
34 #include "pipe/p_state.h"
35 #include "pipe/p_context.h"
36 #include "pipe/p_screen.h"
37 #include "util/detect_os.h"
38 #include "util/os_memory.h"
39 #include "util/u_cpu_detect.h"
40 #include "util/u_inlines.h"
41 #include "util/format/u_format.h"
42 #include "util/u_memory.h"
43 #include "util/u_resource.h"
44 #include "util/u_threaded_context.h"
45 #include "util/u_transfer.h"
46 #include "util/u_transfer_helper.h"
47 #include "util/u_upload_mgr.h"
48 #include "util/ralloc.h"
49 #include "i915/iris_bufmgr.h"
50 #include "iris_batch.h"
51 #include "iris_context.h"
52 #include "iris_resource.h"
53 #include "iris_screen.h"
54 #include "intel/common/intel_aux_map.h"
55 #include "intel/dev/intel_debug.h"
56 #include "isl/isl.h"
57 #include "drm-uapi/drm_fourcc.h"
58 
59 enum modifier_priority {
60    MODIFIER_PRIORITY_INVALID = 0,
61    MODIFIER_PRIORITY_LINEAR,
62    MODIFIER_PRIORITY_X,
63    MODIFIER_PRIORITY_Y,
64    MODIFIER_PRIORITY_Y_CCS,
65    MODIFIER_PRIORITY_Y_GFX12_RC_CCS,
66    MODIFIER_PRIORITY_Y_GFX12_RC_CCS_CC,
67    MODIFIER_PRIORITY_4,
68    MODIFIER_PRIORITY_4_DG2_RC_CCS,
69    MODIFIER_PRIORITY_4_DG2_RC_CCS_CC,
70    MODIFIER_PRIORITY_4_MTL_RC_CCS,
71    MODIFIER_PRIORITY_4_MTL_RC_CCS_CC,
72 };
73 
74 static const uint64_t priority_to_modifier[] = {
75    [MODIFIER_PRIORITY_INVALID] = DRM_FORMAT_MOD_INVALID,
76    [MODIFIER_PRIORITY_LINEAR] = DRM_FORMAT_MOD_LINEAR,
77    [MODIFIER_PRIORITY_X] = I915_FORMAT_MOD_X_TILED,
78    [MODIFIER_PRIORITY_Y] = I915_FORMAT_MOD_Y_TILED,
79    [MODIFIER_PRIORITY_Y_CCS] = I915_FORMAT_MOD_Y_TILED_CCS,
80    [MODIFIER_PRIORITY_Y_GFX12_RC_CCS] = I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS,
81    [MODIFIER_PRIORITY_Y_GFX12_RC_CCS_CC] = I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC,
82    [MODIFIER_PRIORITY_4] = I915_FORMAT_MOD_4_TILED,
83    [MODIFIER_PRIORITY_4_DG2_RC_CCS] = I915_FORMAT_MOD_4_TILED_DG2_RC_CCS,
84    [MODIFIER_PRIORITY_4_DG2_RC_CCS_CC] = I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC,
85    [MODIFIER_PRIORITY_4_MTL_RC_CCS] = I915_FORMAT_MOD_4_TILED_MTL_RC_CCS,
86    [MODIFIER_PRIORITY_4_MTL_RC_CCS_CC] = I915_FORMAT_MOD_4_TILED_MTL_RC_CCS_CC,
87 };
88 
89 static bool
modifier_is_supported(const struct intel_device_info * devinfo,enum pipe_format pfmt,unsigned bind,uint64_t modifier)90 modifier_is_supported(const struct intel_device_info *devinfo,
91                       enum pipe_format pfmt, unsigned bind,
92                       uint64_t modifier)
93 {
94    /* Check for basic device support. */
95    switch (modifier) {
96    case DRM_FORMAT_MOD_LINEAR:
97    case I915_FORMAT_MOD_X_TILED:
98       break;
99    case I915_FORMAT_MOD_Y_TILED:
100       if (devinfo->ver <= 8 && (bind & PIPE_BIND_SCANOUT))
101          return false;
102       if (devinfo->verx10 >= 125)
103          return false;
104       break;
105    case I915_FORMAT_MOD_Y_TILED_CCS:
106       if (devinfo->ver <= 8 || devinfo->ver >= 12)
107          return false;
108       break;
109    case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
110    case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
111    case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC:
112       if (devinfo->verx10 != 120)
113          return false;
114       break;
115    case I915_FORMAT_MOD_4_TILED:
116       if (devinfo->verx10 < 125)
117          return false;
118       break;
119    case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS:
120    case I915_FORMAT_MOD_4_TILED_DG2_MC_CCS:
121    case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC:
122       if (!intel_device_info_is_dg2(devinfo))
123          return false;
124       break;
125    case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS:
126    case I915_FORMAT_MOD_4_TILED_MTL_MC_CCS:
127    case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS_CC:
128       if (!intel_device_info_is_mtl_or_arl(devinfo))
129          return false;
130       break;
131    case DRM_FORMAT_MOD_INVALID:
132    default:
133       return false;
134    }
135 
136    bool no_ccs = INTEL_DEBUG(DEBUG_NO_CCS) || (bind & PIPE_BIND_CONST_BW);
137 
138    /* Check remaining requirements. */
139    switch (modifier) {
140    case I915_FORMAT_MOD_4_TILED_MTL_MC_CCS:
141    case I915_FORMAT_MOD_4_TILED_DG2_MC_CCS:
142    case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
143       if (no_ccs)
144          return false;
145 
146       if (pfmt != PIPE_FORMAT_BGRA8888_UNORM &&
147           pfmt != PIPE_FORMAT_RGBA8888_UNORM &&
148           pfmt != PIPE_FORMAT_BGRX8888_UNORM &&
149           pfmt != PIPE_FORMAT_RGBX8888_UNORM &&
150           pfmt != PIPE_FORMAT_NV12 &&
151           pfmt != PIPE_FORMAT_P010 &&
152           pfmt != PIPE_FORMAT_P012 &&
153           pfmt != PIPE_FORMAT_P016 &&
154           pfmt != PIPE_FORMAT_YUYV &&
155           pfmt != PIPE_FORMAT_UYVY) {
156          return false;
157       }
158       break;
159    case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS:
160    case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS_CC:
161    case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC:
162    case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS:
163    case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC:
164    case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
165    case I915_FORMAT_MOD_Y_TILED_CCS: {
166       if (no_ccs)
167          return false;
168 
169       enum isl_format rt_format =
170          iris_format_for_usage(devinfo, pfmt,
171                                ISL_SURF_USAGE_RENDER_TARGET_BIT).fmt;
172 
173       if (rt_format == ISL_FORMAT_UNSUPPORTED ||
174           !isl_format_supports_ccs_e(devinfo, rt_format))
175          return false;
176       break;
177    }
178    default:
179       break;
180    }
181 
182    return true;
183 }
184 
185 static uint64_t
select_best_modifier(const struct intel_device_info * devinfo,const struct pipe_resource * templ,const uint64_t * modifiers,int count)186 select_best_modifier(const struct intel_device_info *devinfo,
187                      const struct pipe_resource *templ,
188                      const uint64_t *modifiers,
189                      int count)
190 {
191    enum modifier_priority prio = MODIFIER_PRIORITY_INVALID;
192 
193    for (int i = 0; i < count; i++) {
194       if (!modifier_is_supported(devinfo, templ->format, templ->bind,
195                                  modifiers[i]))
196          continue;
197 
198       switch (modifiers[i]) {
199       case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS_CC:
200          prio = MAX2(prio, MODIFIER_PRIORITY_4_MTL_RC_CCS_CC);
201          break;
202       case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS:
203          prio = MAX2(prio, MODIFIER_PRIORITY_4_MTL_RC_CCS);
204          break;
205       case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC:
206          prio = MAX2(prio, MODIFIER_PRIORITY_4_DG2_RC_CCS_CC);
207          break;
208       case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS:
209          prio = MAX2(prio, MODIFIER_PRIORITY_4_DG2_RC_CCS);
210          break;
211       case I915_FORMAT_MOD_4_TILED:
212          prio = MAX2(prio, MODIFIER_PRIORITY_4);
213          break;
214       case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC:
215          prio = MAX2(prio, MODIFIER_PRIORITY_Y_GFX12_RC_CCS_CC);
216          break;
217       case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
218          prio = MAX2(prio, MODIFIER_PRIORITY_Y_GFX12_RC_CCS);
219          break;
220       case I915_FORMAT_MOD_Y_TILED_CCS:
221          prio = MAX2(prio, MODIFIER_PRIORITY_Y_CCS);
222          break;
223       case I915_FORMAT_MOD_Y_TILED:
224          prio = MAX2(prio, MODIFIER_PRIORITY_Y);
225          break;
226       case I915_FORMAT_MOD_X_TILED:
227          prio = MAX2(prio, MODIFIER_PRIORITY_X);
228          break;
229       case DRM_FORMAT_MOD_LINEAR:
230          prio = MAX2(prio, MODIFIER_PRIORITY_LINEAR);
231          break;
232       case DRM_FORMAT_MOD_INVALID:
233       default:
234          break;
235       }
236    }
237 
238    return priority_to_modifier[prio];
239 }
240 
is_modifier_external_only(enum pipe_format pfmt,uint64_t modifier)241 static inline bool is_modifier_external_only(enum pipe_format pfmt,
242                                              uint64_t modifier)
243 {
244    /* Only allow external usage for the following cases: YUV formats
245     * and the media-compression modifier. The render engine lacks
246     * support for rendering to a media-compressed surface if the
247     * compression ratio is large enough. By requiring external usage
248     * of media-compressed surfaces, resolves are avoided.
249     */
250    return util_format_is_yuv(pfmt) ||
251           isl_drm_modifier_get_info(modifier)->supports_media_compression;
252 }
253 
254 static void
iris_query_dmabuf_modifiers(struct pipe_screen * pscreen,enum pipe_format pfmt,int max,uint64_t * modifiers,unsigned int * external_only,int * count)255 iris_query_dmabuf_modifiers(struct pipe_screen *pscreen,
256                             enum pipe_format pfmt,
257                             int max,
258                             uint64_t *modifiers,
259                             unsigned int *external_only,
260                             int *count)
261 {
262    struct iris_screen *screen = (void *) pscreen;
263    const struct intel_device_info *devinfo = screen->devinfo;
264 
265    uint64_t all_modifiers[] = {
266       DRM_FORMAT_MOD_LINEAR,
267       I915_FORMAT_MOD_X_TILED,
268       I915_FORMAT_MOD_4_TILED,
269       I915_FORMAT_MOD_4_TILED_DG2_RC_CCS,
270       I915_FORMAT_MOD_4_TILED_DG2_MC_CCS,
271       I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC,
272       I915_FORMAT_MOD_4_TILED_MTL_RC_CCS,
273       I915_FORMAT_MOD_4_TILED_MTL_RC_CCS_CC,
274       I915_FORMAT_MOD_4_TILED_MTL_MC_CCS,
275       I915_FORMAT_MOD_Y_TILED,
276       I915_FORMAT_MOD_Y_TILED_CCS,
277       I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS,
278       I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS,
279       I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC,
280    };
281 
282    int supported_mods = 0;
283 
284    for (int i = 0; i < ARRAY_SIZE(all_modifiers); i++) {
285       if (!modifier_is_supported(devinfo, pfmt, 0, all_modifiers[i]))
286          continue;
287 
288       if (supported_mods < max) {
289          if (modifiers)
290             modifiers[supported_mods] = all_modifiers[i];
291 
292          if (external_only) {
293             external_only[supported_mods] =
294                is_modifier_external_only(pfmt, all_modifiers[i]);
295          }
296       }
297 
298       supported_mods++;
299    }
300 
301    *count = supported_mods;
302 }
303 
304 static bool
iris_is_dmabuf_modifier_supported(struct pipe_screen * pscreen,uint64_t modifier,enum pipe_format pfmt,bool * external_only)305 iris_is_dmabuf_modifier_supported(struct pipe_screen *pscreen,
306                                   uint64_t modifier, enum pipe_format pfmt,
307                                   bool *external_only)
308 {
309    struct iris_screen *screen = (void *) pscreen;
310    const struct intel_device_info *devinfo = screen->devinfo;
311 
312    if (modifier_is_supported(devinfo, pfmt, 0, modifier)) {
313       if (external_only)
314          *external_only = is_modifier_external_only(pfmt, modifier);
315 
316       return true;
317    }
318 
319    return false;
320 }
321 
322 static unsigned int
iris_get_dmabuf_modifier_planes(struct pipe_screen * pscreen,uint64_t modifier,enum pipe_format format)323 iris_get_dmabuf_modifier_planes(struct pipe_screen *pscreen, uint64_t modifier,
324                                 enum pipe_format format)
325 {
326    unsigned int planes = util_format_get_num_planes(format);
327 
328    switch (modifier) {
329    case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS_CC:
330    case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC:
331       return 3;
332    case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS:
333    case I915_FORMAT_MOD_4_TILED_MTL_MC_CCS:
334    case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC:
335    case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
336    case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
337    case I915_FORMAT_MOD_Y_TILED_CCS:
338       return 2 * planes;
339    case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS:
340    case I915_FORMAT_MOD_4_TILED_DG2_MC_CCS:
341    default:
342       return planes;
343    }
344 }
345 
346 enum isl_format
iris_image_view_get_format(struct iris_context * ice,const struct pipe_image_view * img)347 iris_image_view_get_format(struct iris_context *ice,
348                            const struct pipe_image_view *img)
349 {
350    struct iris_screen *screen = (struct iris_screen *)ice->ctx.screen;
351    const struct intel_device_info *devinfo = screen->devinfo;
352 
353    isl_surf_usage_flags_t usage = ISL_SURF_USAGE_STORAGE_BIT;
354    enum isl_format isl_fmt =
355       iris_format_for_usage(devinfo, img->format, usage).fmt;
356 
357    if (img->shader_access & PIPE_IMAGE_ACCESS_READ) {
358       /* On Gfx8, try to use typed surfaces reads (which support a
359        * limited number of formats), and if not possible, fall back
360        * to untyped reads.
361        */
362       if (devinfo->ver == 8 &&
363           !isl_has_matching_typed_storage_image_format(devinfo, isl_fmt))
364          return ISL_FORMAT_RAW;
365       else
366          return isl_lower_storage_image_format(devinfo, isl_fmt);
367    }
368 
369    return isl_fmt;
370 }
371 
372 static struct pipe_memory_object *
iris_memobj_create_from_handle(struct pipe_screen * pscreen,struct winsys_handle * whandle,bool dedicated)373 iris_memobj_create_from_handle(struct pipe_screen *pscreen,
374                                struct winsys_handle *whandle,
375                                bool dedicated)
376 {
377    struct iris_screen *screen = (struct iris_screen *)pscreen;
378    struct iris_memory_object *memobj = CALLOC_STRUCT(iris_memory_object);
379    if (!memobj)
380       return NULL;
381 
382    assert(whandle->type == WINSYS_HANDLE_TYPE_FD);
383    assert(whandle->modifier == DRM_FORMAT_MOD_INVALID);
384    struct iris_bo *bo = iris_bo_import_dmabuf(screen->bufmgr, whandle->handle,
385                                               DRM_FORMAT_MOD_INVALID);
386    if (!bo) {
387       free(memobj);
388       return NULL;
389    }
390 
391    memobj->b.dedicated = dedicated;
392    memobj->bo = bo;
393    memobj->format = whandle->format;
394    memobj->stride = whandle->stride;
395 
396    return &memobj->b;
397 }
398 
399 static void
iris_memobj_destroy(struct pipe_screen * pscreen,struct pipe_memory_object * pmemobj)400 iris_memobj_destroy(struct pipe_screen *pscreen,
401                     struct pipe_memory_object *pmemobj)
402 {
403    struct iris_memory_object *memobj = (struct iris_memory_object *)pmemobj;
404 
405    iris_bo_unreference(memobj->bo);
406    free(memobj);
407 }
408 
409 struct pipe_resource *
iris_resource_get_separate_stencil(struct pipe_resource * p_res)410 iris_resource_get_separate_stencil(struct pipe_resource *p_res)
411 {
412    /* For packed depth-stencil, we treat depth as the primary resource
413     * and store S8 as the "second plane" resource.
414     */
415    if (p_res->next && p_res->next->format == PIPE_FORMAT_S8_UINT)
416       return p_res->next;
417 
418    return NULL;
419 
420 }
421 
422 static void
iris_resource_set_separate_stencil(struct pipe_resource * p_res,struct pipe_resource * stencil)423 iris_resource_set_separate_stencil(struct pipe_resource *p_res,
424                                    struct pipe_resource *stencil)
425 {
426    assert(util_format_has_depth(util_format_description(p_res->format)));
427    pipe_resource_reference(&p_res->next, stencil);
428 }
429 
430 void
iris_get_depth_stencil_resources(struct pipe_resource * res,struct iris_resource ** out_z,struct iris_resource ** out_s)431 iris_get_depth_stencil_resources(struct pipe_resource *res,
432                                  struct iris_resource **out_z,
433                                  struct iris_resource **out_s)
434 {
435    if (!res) {
436       *out_z = NULL;
437       *out_s = NULL;
438       return;
439    }
440 
441    if (res->format != PIPE_FORMAT_S8_UINT) {
442       *out_z = (void *) res;
443       *out_s = (void *) iris_resource_get_separate_stencil(res);
444    } else {
445       *out_z = NULL;
446       *out_s = (void *) res;
447    }
448 }
449 
450 void
iris_resource_disable_aux(struct iris_resource * res)451 iris_resource_disable_aux(struct iris_resource *res)
452 {
453    iris_bo_unreference(res->aux.bo);
454    iris_bo_unreference(res->aux.clear_color_bo);
455    free(res->aux.state);
456 
457    res->aux.usage = ISL_AUX_USAGE_NONE;
458    res->aux.surf.size_B = 0;
459    res->aux.bo = NULL;
460    res->aux.clear_color_bo = NULL;
461    res->aux.state = NULL;
462 }
463 
464 static unsigned
iris_resource_alloc_flags(const struct iris_screen * screen,const struct pipe_resource * templ,struct iris_resource * res)465 iris_resource_alloc_flags(const struct iris_screen *screen,
466                           const struct pipe_resource *templ,
467                           struct iris_resource *res)
468 {
469    if (templ->flags & IRIS_RESOURCE_FLAG_DEVICE_MEM)
470       return BO_ALLOC_PLAIN;
471 
472    unsigned flags = BO_ALLOC_PLAIN;
473 
474    switch (templ->usage) {
475    case PIPE_USAGE_STAGING:
476       flags |= BO_ALLOC_SMEM | BO_ALLOC_COHERENT;
477       break;
478    case PIPE_USAGE_STREAM:
479       flags |= BO_ALLOC_SMEM;
480       break;
481    case PIPE_USAGE_DYNAMIC:
482    case PIPE_USAGE_DEFAULT:
483    case PIPE_USAGE_IMMUTABLE:
484       /* Use LMEM for these if possible */
485       break;
486    }
487 
488    if (templ->bind & PIPE_BIND_SCANOUT)
489       flags |= BO_ALLOC_SCANOUT;
490 
491    if (templ->flags & (PIPE_RESOURCE_FLAG_MAP_COHERENT |
492                        PIPE_RESOURCE_FLAG_MAP_PERSISTENT))
493       flags |= BO_ALLOC_SMEM | BO_ALLOC_COHERENT;
494 
495    if (screen->devinfo->verx10 >= 125 && screen->devinfo->has_local_mem &&
496        isl_aux_usage_has_ccs(res->aux.usage)) {
497       assert((flags & BO_ALLOC_SMEM) == 0);
498       flags |= BO_ALLOC_LMEM;
499       /* For displayable surfaces with clear color,
500        * the KMD will need to access the clear color via CPU.
501        */
502       if (res->mod_info && res->mod_info->supports_clear_color)
503          flags |= BO_ALLOC_CPU_VISIBLE;
504    }
505 
506    if ((templ->bind & PIPE_BIND_SHARED) ||
507        util_format_get_num_planes(templ->format) > 1)
508       flags |= BO_ALLOC_NO_SUBALLOC;
509 
510    if (templ->bind & PIPE_BIND_PROTECTED)
511       flags |= BO_ALLOC_PROTECTED;
512 
513    if (templ->bind & PIPE_BIND_SHARED) {
514       flags |= BO_ALLOC_SHARED;
515 
516       /* We request that the bufmgr zero because, if a buffer gets re-used
517        * from the pool, we don't want to leak random garbage from our process
518        * to some other.
519        */
520       flags |= BO_ALLOC_ZEROED;
521    }
522 
523    return flags;
524 }
525 
526 static void
iris_resource_destroy(struct pipe_screen * screen,struct pipe_resource * p_res)527 iris_resource_destroy(struct pipe_screen *screen,
528                       struct pipe_resource *p_res)
529 {
530    struct iris_resource *res = (struct iris_resource *) p_res;
531 
532    if (p_res->target == PIPE_BUFFER)
533       util_range_destroy(&res->valid_buffer_range);
534 
535    iris_resource_disable_aux(res);
536 
537    threaded_resource_deinit(p_res);
538    iris_bo_unreference(res->bo);
539    iris_pscreen_unref(res->orig_screen);
540 
541    free(res);
542 }
543 
544 static struct iris_resource *
iris_alloc_resource(struct pipe_screen * pscreen,const struct pipe_resource * templ)545 iris_alloc_resource(struct pipe_screen *pscreen,
546                     const struct pipe_resource *templ)
547 {
548    struct iris_resource *res = calloc(1, sizeof(struct iris_resource));
549    if (!res)
550       return NULL;
551 
552    res->base.b = *templ;
553    res->base.b.screen = pscreen;
554    res->orig_screen = iris_pscreen_ref(pscreen);
555    pipe_reference_init(&res->base.b.reference, 1);
556    threaded_resource_init(&res->base.b, false);
557 
558    if (templ->target == PIPE_BUFFER)
559       util_range_init(&res->valid_buffer_range);
560 
561    return res;
562 }
563 
564 unsigned
iris_get_num_logical_layers(const struct iris_resource * res,unsigned level)565 iris_get_num_logical_layers(const struct iris_resource *res, unsigned level)
566 {
567    if (res->surf.dim == ISL_SURF_DIM_3D)
568       return u_minify(res->surf.logical_level0_px.depth, level);
569    else
570       return res->surf.logical_level0_px.array_len;
571 }
572 
573 static enum isl_aux_state **
create_aux_state_map(struct iris_resource * res,enum isl_aux_state initial)574 create_aux_state_map(struct iris_resource *res, enum isl_aux_state initial)
575 {
576    assert(res->aux.state == NULL);
577 
578    uint32_t total_slices = 0;
579    for (uint32_t level = 0; level < res->surf.levels; level++)
580       total_slices += iris_get_num_logical_layers(res, level);
581 
582    const size_t per_level_array_size =
583       res->surf.levels * sizeof(enum isl_aux_state *);
584 
585    /* We're going to allocate a single chunk of data for both the per-level
586     * reference array and the arrays of aux_state.  This makes cleanup
587     * significantly easier.
588     */
589    const size_t total_size =
590       per_level_array_size + total_slices * sizeof(enum isl_aux_state);
591 
592    void *data = malloc(total_size);
593    if (!data)
594       return NULL;
595 
596    enum isl_aux_state **per_level_arr = data;
597    enum isl_aux_state *s = data + per_level_array_size;
598    for (uint32_t level = 0; level < res->surf.levels; level++) {
599       per_level_arr[level] = s;
600       const unsigned level_layers = iris_get_num_logical_layers(res, level);
601       for (uint32_t a = 0; a < level_layers; a++)
602          *(s++) = initial;
603    }
604    assert((void *)s == data + total_size);
605 
606    return per_level_arr;
607 }
608 
609 static unsigned
iris_get_aux_clear_color_state_size(struct iris_screen * screen,struct iris_resource * res)610 iris_get_aux_clear_color_state_size(struct iris_screen *screen,
611                                     struct iris_resource *res)
612 {
613    if (!isl_aux_usage_has_fast_clears(res->aux.usage))
614       return 0;
615 
616    assert(!isl_surf_usage_is_stencil(res->surf.usage));
617 
618    /* Depth packets can't specify indirect clear values. The only time depth
619     * buffers can use indirect clear values is when they're accessed by the
620     * sampler via render surface state objects.
621     */
622    if (isl_surf_usage_is_depth(res->surf.usage) &&
623        !iris_sample_with_depth_aux(screen->devinfo, res))
624       return 0;
625 
626    return screen->isl_dev.ss.clear_color_state_size;
627 }
628 
629 static void
map_aux_addresses(struct iris_screen * screen,struct iris_resource * res,enum pipe_format pfmt,unsigned plane)630 map_aux_addresses(struct iris_screen *screen, struct iris_resource *res,
631                   enum pipe_format pfmt, unsigned plane)
632 {
633    void *aux_map_ctx = iris_bufmgr_get_aux_map_context(screen->bufmgr);
634    if (!aux_map_ctx)
635       return;
636 
637    if (isl_aux_usage_has_ccs(res->aux.usage)) {
638       const enum isl_format format =
639          iris_format_for_usage(screen->devinfo, pfmt, res->surf.usage).fmt;
640       const uint64_t format_bits =
641          intel_aux_map_format_bits(res->surf.tiling, format, plane);
642       const bool mapped =
643          intel_aux_map_add_mapping(aux_map_ctx,
644                                    res->bo->address + res->offset,
645                                    res->aux.bo->address +
646                                    res->aux.comp_ctrl_surf_offset,
647                                    res->surf.size_B, format_bits);
648       assert(mapped);
649       res->bo->aux_map_address = res->aux.bo->address;
650    }
651 }
652 
653 static bool
want_ccs_e_for_format(const struct intel_device_info * devinfo,enum isl_format format)654 want_ccs_e_for_format(const struct intel_device_info *devinfo,
655                       enum isl_format format)
656 {
657    if (!isl_format_supports_ccs_e(devinfo, format))
658       return false;
659 
660    const struct isl_format_layout *fmtl = isl_format_get_layout(format);
661 
662    /* Prior to TGL, CCS_E seems to significantly hurt performance with 32-bit
663     * floating point formats.  For example, Paraview's "Wavelet Volume" case
664     * uses both R32_FLOAT and R32G32B32A32_FLOAT, and enabling CCS_E for those
665     * formats causes a 62% FPS drop.
666     *
667     * However, many benchmarks seem to use 16-bit float with no issues.
668     */
669    if (devinfo->ver <= 11 &&
670        fmtl->channels.r.bits == 32 && fmtl->channels.r.type == ISL_SFLOAT)
671       return false;
672 
673    return true;
674 }
675 
676 static bool
want_hiz_wt_for_res(const struct intel_device_info * devinfo,const struct iris_resource * res)677 want_hiz_wt_for_res(const struct intel_device_info *devinfo,
678                     const struct iris_resource *res)
679 {
680    /* Gen12 only supports single-sampled while Gen20+ supports
681     * multi-sampled images.
682     */
683    if (devinfo->ver < 20 && res->surf.samples > 1)
684       return false;
685 
686    if (!(res->surf.usage & ISL_SURF_USAGE_TEXTURE_BIT))
687       return false;
688 
689    /* If this resource has the maximum number of samples supported by
690     * running platform and will be used as a texture, put the HiZ surface
691     * in write-through mode so that we can sample from it.
692     */
693    return true;
694 }
695 
696 static enum isl_surf_dim
target_to_isl_surf_dim(enum pipe_texture_target target)697 target_to_isl_surf_dim(enum pipe_texture_target target)
698 {
699    switch (target) {
700    case PIPE_BUFFER:
701    case PIPE_TEXTURE_1D:
702    case PIPE_TEXTURE_1D_ARRAY:
703       return ISL_SURF_DIM_1D;
704    case PIPE_TEXTURE_2D:
705    case PIPE_TEXTURE_CUBE:
706    case PIPE_TEXTURE_RECT:
707    case PIPE_TEXTURE_2D_ARRAY:
708    case PIPE_TEXTURE_CUBE_ARRAY:
709       return ISL_SURF_DIM_2D;
710    case PIPE_TEXTURE_3D:
711       return ISL_SURF_DIM_3D;
712    case PIPE_MAX_TEXTURE_TYPES:
713       break;
714    }
715    unreachable("invalid texture type");
716 }
717 
718 static bool
iris_resource_configure_main(const struct iris_screen * screen,struct iris_resource * res,const struct pipe_resource * templ,uint64_t modifier,uint32_t row_pitch_B)719 iris_resource_configure_main(const struct iris_screen *screen,
720                              struct iris_resource *res,
721                              const struct pipe_resource *templ,
722                              uint64_t modifier, uint32_t row_pitch_B)
723 {
724    res->mod_info = isl_drm_modifier_get_info(modifier);
725 
726    if (modifier != DRM_FORMAT_MOD_INVALID && res->mod_info == NULL)
727       return false;
728 
729    isl_tiling_flags_t tiling_flags = 0;
730 
731    if (res->mod_info != NULL) {
732       tiling_flags = 1 << res->mod_info->tiling;
733    } else if (templ->usage == PIPE_USAGE_STAGING ||
734               templ->bind & (PIPE_BIND_LINEAR | PIPE_BIND_CURSOR)) {
735       tiling_flags = ISL_TILING_LINEAR_BIT;
736    } else if (res->external_format != PIPE_FORMAT_NONE) {
737       /* This came from iris_resource_from_memobj and didn't have
738        * PIPE_BIND_LINEAR set, so "optimal" tiling is desired.  Let isl
739        * select the tiling.  The implicit contract is that both drivers
740        * will arrive at the same tiling by using the same code to decide.
741        */
742       assert(modifier == DRM_FORMAT_MOD_INVALID);
743       tiling_flags = ISL_TILING_ANY_MASK;
744    } else if (!screen->devinfo->has_tiling_uapi &&
745               (templ->bind & (PIPE_BIND_SCANOUT | PIPE_BIND_SHARED))) {
746       tiling_flags = ISL_TILING_LINEAR_BIT;
747    } else if (templ->bind & PIPE_BIND_SCANOUT) {
748       tiling_flags = ISL_TILING_X_BIT;
749    } else {
750       tiling_flags = ISL_TILING_ANY_MASK;
751    }
752 
753    /* We don't support Yf or Ys tiling yet */
754    tiling_flags &= ~ISL_TILING_STD_Y_MASK;
755    assert(tiling_flags != 0);
756 
757    isl_surf_usage_flags_t usage = 0;
758 
759    if (res->mod_info && !isl_drm_modifier_has_aux(modifier))
760       usage |= ISL_SURF_USAGE_DISABLE_AUX_BIT;
761 
762    else if (!res->mod_info && res->external_format != PIPE_FORMAT_NONE)
763       usage |= ISL_SURF_USAGE_DISABLE_AUX_BIT;
764 
765    else if (templ->bind & PIPE_BIND_CONST_BW)
766       usage |= ISL_SURF_USAGE_DISABLE_AUX_BIT;
767 
768    if (templ->usage == PIPE_USAGE_STAGING)
769       usage |= ISL_SURF_USAGE_STAGING_BIT;
770 
771    if (templ->bind & PIPE_BIND_RENDER_TARGET)
772       usage |= ISL_SURF_USAGE_RENDER_TARGET_BIT;
773 
774    if (templ->bind & PIPE_BIND_SAMPLER_VIEW)
775       usage |= ISL_SURF_USAGE_TEXTURE_BIT;
776 
777    if (templ->bind & PIPE_BIND_SHADER_IMAGE)
778       usage |= ISL_SURF_USAGE_STORAGE_BIT;
779 
780    if (templ->bind & PIPE_BIND_SCANOUT)
781       usage |= ISL_SURF_USAGE_DISPLAY_BIT;
782 
783    else if (isl_drm_modifier_needs_display_layout(modifier))
784       usage |= ISL_SURF_USAGE_DISPLAY_BIT;
785 
786    if (templ->target == PIPE_TEXTURE_CUBE ||
787        templ->target == PIPE_TEXTURE_CUBE_ARRAY) {
788       usage |= ISL_SURF_USAGE_CUBE_BIT;
789    }
790 
791    if (templ->usage != PIPE_USAGE_STAGING &&
792        util_format_is_depth_or_stencil(templ->format)) {
793 
794       /* Should be handled by u_transfer_helper */
795       assert(!util_format_is_depth_and_stencil(templ->format));
796 
797       usage |= templ->format == PIPE_FORMAT_S8_UINT ?
798                ISL_SURF_USAGE_STENCIL_BIT : ISL_SURF_USAGE_DEPTH_BIT;
799    }
800 
801    if ((usage & ISL_SURF_USAGE_TEXTURE_BIT) ||
802        !isl_surf_usage_is_depth_or_stencil(usage)) {
803       /* Notify ISL that iris may access this image from different engines.
804        * The reads and writes performed by the engines are guaranteed to be
805        * sequential with respect to each other. This is due to the
806        * implementation of flush_for_cross_batch_dependencies().
807        */
808       usage |= ISL_SURF_USAGE_MULTI_ENGINE_SEQ_BIT;
809    } else {
810       /* Depth/stencil render buffers are the only surfaces which are not
811        * accessed by compute shaders. Also, iris does not use the blitter on
812        * such surfaces.
813        */
814      assert(!(templ->bind & PIPE_BIND_SHADER_IMAGE));
815      assert(!(templ->bind & PIPE_BIND_PRIME_BLIT_DST));
816    }
817 
818    const enum isl_format format =
819       iris_format_for_usage(screen->devinfo, templ->format, usage).fmt;
820 
821    const struct isl_surf_init_info init_info = {
822       .dim = target_to_isl_surf_dim(templ->target),
823       .format = format,
824       .width = templ->width0,
825       .height = templ->height0,
826       .depth = templ->depth0,
827       .levels = templ->last_level + 1,
828       .array_len = templ->array_size,
829       .samples = MAX2(templ->nr_samples, 1),
830       .min_alignment_B = 0,
831       .row_pitch_B = row_pitch_B,
832       .usage = usage,
833       .tiling_flags = tiling_flags
834    };
835 
836    if (!isl_surf_init_s(&screen->isl_dev, &res->surf, &init_info))
837       return false;
838 
839    res->internal_format = templ->format;
840 
841    return true;
842 }
843 
844 /**
845  * Configure aux for the resource, but don't allocate it. For images which
846  * might be shared with modifiers, we must allocate the image and aux data in
847  * a single bo.
848  *
849  * Returns false on unexpected error (e.g. allocation failed, or invalid
850  * configuration result).
851  */
852 static bool
iris_resource_configure_aux(struct iris_screen * screen,struct iris_resource * res)853 iris_resource_configure_aux(struct iris_screen *screen,
854                             struct iris_resource *res)
855 {
856    const struct intel_device_info *devinfo = screen->devinfo;
857 
858    const bool has_mcs =
859       isl_surf_get_mcs_surf(&screen->isl_dev, &res->surf, &res->aux.surf);
860 
861    const bool has_hiz =
862       isl_surf_get_hiz_surf(&screen->isl_dev, &res->surf, &res->aux.surf);
863 
864    const bool has_ccs = devinfo->has_aux_map || devinfo->has_flat_ccs ?
865       isl_surf_supports_ccs(&screen->isl_dev, &res->surf, &res->aux.surf) :
866       isl_surf_get_ccs_surf(&screen->isl_dev, &res->surf, &res->aux.surf, 0);
867 
868    if (has_mcs) {
869       assert(!res->mod_info);
870       assert(!has_hiz);
871       /* We are seeing failures with CCS compression on top of MSAA
872        * compression, so just enable MSAA compression for now on DG2.
873        */
874       if (!intel_device_info_is_dg2(devinfo) && has_ccs) {
875          res->aux.usage = ISL_AUX_USAGE_MCS_CCS;
876       } else {
877          res->aux.usage = ISL_AUX_USAGE_MCS;
878       }
879    } else if (has_hiz) {
880       assert(!res->mod_info);
881       assert(!has_mcs);
882       if (!has_ccs) {
883          res->aux.usage = ISL_AUX_USAGE_HIZ;
884       } else if (want_hiz_wt_for_res(devinfo, res)) {
885          res->aux.usage = ISL_AUX_USAGE_HIZ_CCS_WT;
886       } else {
887          res->aux.usage = ISL_AUX_USAGE_HIZ_CCS;
888       }
889    } else if (has_ccs) {
890       if (isl_surf_usage_is_stencil(res->surf.usage)) {
891          assert(!res->mod_info);
892          res->aux.usage = ISL_AUX_USAGE_STC_CCS;
893       } else if (res->mod_info && res->mod_info->supports_media_compression) {
894          res->aux.usage = ISL_AUX_USAGE_MC;
895       } else if (want_ccs_e_for_format(devinfo, res->surf.format)) {
896          res->aux.usage = intel_needs_workaround(devinfo, 1607794140) ?
897             ISL_AUX_USAGE_FCV_CCS_E : ISL_AUX_USAGE_CCS_E;
898       } else {
899          assert(isl_format_supports_ccs_d(devinfo, res->surf.format));
900          res->aux.usage = ISL_AUX_USAGE_CCS_D;
901       }
902    }
903 
904    if (res->mod_info &&
905        isl_drm_modifier_has_aux(res->mod_info->modifier) != has_ccs) {
906       return false;
907    }
908 
909    return true;
910 }
911 
912 /**
913  * Initialize the aux buffer contents.
914  *
915  * Returns false on unexpected error (e.g. mapping a BO failed).
916  */
917 static bool
iris_resource_init_aux_buf(struct iris_screen * screen,struct iris_resource * res)918 iris_resource_init_aux_buf(struct iris_screen *screen,
919                            struct iris_resource *res)
920 {
921    const struct intel_device_info *devinfo = screen->devinfo;
922 
923    if (isl_aux_usage_has_ccs(res->aux.usage) && devinfo->ver <= 11) {
924       /* Initialize the CCS on BDW-ICL to the PASS_THROUGH state. This avoids
925        * the need to ambiguate in some cases.
926        */
927       void* map = iris_bo_map(NULL, res->bo, MAP_WRITE | MAP_RAW);
928       if (!map)
929          return false;
930 
931       memset((char*)map + res->aux.offset, 0, res->aux.surf.size_B);
932       iris_bo_unmap(res->bo);
933 
934       res->aux.state = create_aux_state_map(res, ISL_AUX_STATE_PASS_THROUGH);
935    } else {
936       const enum isl_aux_state initial_state =
937          isl_aux_get_initial_state(devinfo, res->aux.usage, res->bo->zeroed);
938       res->aux.state = create_aux_state_map(res, initial_state);
939    }
940    if (!res->aux.state)
941       return false;
942 
943    if (res->aux.offset > 0 || res->aux.comp_ctrl_surf_offset > 0) {
944       res->aux.bo = res->bo;
945       iris_bo_reference(res->aux.bo);
946       map_aux_addresses(screen, res, res->internal_format, 0);
947    }
948 
949    if (res->aux.clear_color_offset > 0) {
950       res->aux.clear_color_bo = res->bo;
951       iris_bo_reference(res->aux.clear_color_bo);
952       res->aux.clear_color_unknown = !res->aux.clear_color_bo->zeroed;
953    }
954 
955    return true;
956 }
957 
958 static uint32_t
iris_buffer_alignment(uint64_t size)959 iris_buffer_alignment(uint64_t size)
960 {
961    /* Some buffer operations want some amount of alignment.  The largest
962     * buffer texture pixel size is 4 * 4 = 16B.  OpenCL data is also supposed
963     * to be aligned and largest OpenCL data type is a double16 which is
964     * 8 * 16 = 128B.  Align to the largest power of 2 which fits in the size,
965     * up to 128B.
966     */
967    uint32_t align = MAX2(4 * 4, 8 * 16);
968    while (align > size)
969       align >>= 1;
970 
971    return align;
972 }
973 
974 static struct pipe_resource *
iris_resource_create_for_buffer(struct pipe_screen * pscreen,const struct pipe_resource * templ)975 iris_resource_create_for_buffer(struct pipe_screen *pscreen,
976                                 const struct pipe_resource *templ)
977 {
978    struct iris_screen *screen = (struct iris_screen *)pscreen;
979    struct iris_resource *res = iris_alloc_resource(pscreen, templ);
980 
981    assert(templ->target == PIPE_BUFFER);
982    assert(templ->height0 <= 1);
983    assert(templ->depth0 <= 1);
984    assert(templ->format == PIPE_FORMAT_NONE ||
985           util_format_get_blocksize(templ->format) == 1);
986 
987    res->internal_format = templ->format;
988    res->surf.tiling = ISL_TILING_LINEAR;
989 
990    enum iris_memory_zone memzone = IRIS_MEMZONE_OTHER;
991    const char *name = templ->target == PIPE_BUFFER ? "buffer" : "miptree";
992    if (templ->flags & IRIS_RESOURCE_FLAG_SHADER_MEMZONE) {
993       memzone = IRIS_MEMZONE_SHADER;
994       name = "shader kernels";
995    } else if (templ->flags & IRIS_RESOURCE_FLAG_SURFACE_MEMZONE) {
996       memzone = IRIS_MEMZONE_SURFACE;
997       name = "surface state";
998    } else if (templ->flags & IRIS_RESOURCE_FLAG_DYNAMIC_MEMZONE) {
999       memzone = IRIS_MEMZONE_DYNAMIC;
1000       name = "dynamic state";
1001    } else if (templ->flags & IRIS_RESOURCE_FLAG_SCRATCH_MEMZONE) {
1002       memzone = IRIS_MEMZONE_SCRATCH;
1003       name = "scratch surface state";
1004    }
1005 
1006    unsigned flags = iris_resource_alloc_flags(screen, templ, res);
1007 
1008    res->bo = iris_bo_alloc(screen->bufmgr, name, templ->width0,
1009                            iris_buffer_alignment(templ->width0),
1010                            memzone, flags);
1011 
1012    if (!res->bo) {
1013       iris_resource_destroy(pscreen, &res->base.b);
1014       return NULL;
1015    }
1016 
1017    if (templ->bind & PIPE_BIND_SHARED) {
1018       iris_bo_mark_exported(res->bo);
1019       res->base.is_shared = true;
1020    }
1021 
1022    return &res->base.b;
1023 }
1024 
1025 static bool
iris_resource_image_is_pat_compressible(const struct iris_screen * screen,const struct pipe_resource * templ,struct iris_resource * res,unsigned flags)1026 iris_resource_image_is_pat_compressible(const struct iris_screen *screen,
1027                                         const struct pipe_resource *templ,
1028                                         struct iris_resource *res,
1029                                         unsigned flags)
1030 {
1031    assert(templ->target != PIPE_BUFFER);
1032 
1033    if (INTEL_DEBUG(DEBUG_NO_CCS))
1034       return false;
1035 
1036    if (screen->devinfo->ver < 20)
1037       return false;
1038 
1039    if (flags & (BO_ALLOC_PROTECTED |
1040                 BO_ALLOC_COHERENT |
1041                 BO_ALLOC_CPU_VISIBLE))
1042       return false;
1043 
1044    struct iris_bufmgr *bufmgr = screen->bufmgr;
1045    if ((iris_bufmgr_vram_size(bufmgr) > 0) && (flags & BO_ALLOC_SMEM))
1046       return false;
1047 
1048    /* We don't have modifiers with compression enabled on Xe2 so far. */
1049    if (res->mod_info) {
1050       assert(!isl_drm_modifier_has_aux(res->mod_info->modifier));
1051       return false;
1052    }
1053 
1054    /* Bspec 58797 (r58646):
1055     *
1056     *    Enabling compression is not legal for TileX surfaces.
1057     */
1058    if (res->surf.tiling == ISL_TILING_X)
1059       return false;
1060 
1061    /* Bspec 71650 (r59764):
1062     *
1063     *    3 SW  must disable or resolve compression
1064     *       Display: Access to anything except Tile4 Framebuffers...
1065     *          Display Page Tables
1066     *          Display State Buffers
1067     *          Linear/TileX Framebuffers
1068     *          Display Write-Back Buffers
1069     *          Etc.
1070     *
1071     * So far, we don't support resolving on Xe2 and may not want to enable
1072     * compression under these conditions later, so we only enable it when
1073     * a TILING_4 image is to display.
1074     */
1075    if ((flags & BO_ALLOC_SCANOUT) && res->surf.tiling != ISL_TILING_4) {
1076       assert(res->surf.tiling == ISL_TILING_LINEAR);
1077       return false;
1078    }
1079 
1080    return true;
1081 }
1082 
1083 static struct pipe_resource *
iris_resource_create_for_image(struct pipe_screen * pscreen,const struct pipe_resource * templ,const uint64_t * modifiers,int modifiers_count,unsigned row_pitch_B)1084 iris_resource_create_for_image(struct pipe_screen *pscreen,
1085                                const struct pipe_resource *templ,
1086                                const uint64_t *modifiers,
1087                                int modifiers_count,
1088                                unsigned row_pitch_B)
1089 {
1090    struct iris_screen *screen = (struct iris_screen *)pscreen;
1091    const struct intel_device_info *devinfo = screen->devinfo;
1092    struct iris_resource *res = iris_alloc_resource(pscreen, templ);
1093 
1094    if (!res)
1095       return NULL;
1096 
1097    uint64_t modifier =
1098       select_best_modifier(devinfo, templ, modifiers, modifiers_count);
1099 
1100    if (modifier == DRM_FORMAT_MOD_INVALID && modifiers_count > 0) {
1101       fprintf(stderr, "Unsupported modifier, resource creation failed.\n");
1102       goto fail;
1103    }
1104 
1105    const bool isl_surf_created_successfully =
1106       iris_resource_configure_main(screen, res, templ, modifier, row_pitch_B);
1107    if (!isl_surf_created_successfully)
1108       goto fail;
1109 
1110    /* Don't create staging surfaces that will use over half the sram,
1111     * since staging implies you are copying data to another resource that's
1112     * at least as large, and then both wouldn't fit in system memory.
1113     *
1114     * Skip this for discrete cards, as the destination buffer might be in
1115     * device local memory while the staging buffer would be in system memory,
1116     * so both would fit.
1117     */
1118    if (templ->usage == PIPE_USAGE_STAGING && !devinfo->has_local_mem &&
1119        res->surf.size_B > (iris_bufmgr_sram_size(screen->bufmgr) / 2))
1120       goto fail;
1121 
1122    if (!iris_resource_configure_aux(screen, res))
1123       goto fail;
1124 
1125    const char *name = "miptree";
1126    enum iris_memory_zone memzone = IRIS_MEMZONE_OTHER;
1127 
1128    unsigned flags = iris_resource_alloc_flags(screen, templ, res);
1129 
1130    if (iris_resource_image_is_pat_compressible(screen, templ, res, flags))
1131       flags |= BO_ALLOC_COMPRESSED;
1132 
1133    /* These are for u_upload_mgr buffers only */
1134    assert(!(templ->flags & (IRIS_RESOURCE_FLAG_SHADER_MEMZONE |
1135                             IRIS_RESOURCE_FLAG_SURFACE_MEMZONE |
1136                             IRIS_RESOURCE_FLAG_DYNAMIC_MEMZONE |
1137                             IRIS_RESOURCE_FLAG_SCRATCH_MEMZONE)));
1138 
1139    /* Modifiers require the aux data to be in the same buffer as the main
1140     * surface, but we combine them even when a modifier is not being used.
1141     */
1142    uint64_t bo_size = res->surf.size_B;
1143 
1144    /* Allocate space for the aux buffer. */
1145    if (res->aux.surf.size_B > 0) {
1146       res->aux.offset = (uint32_t)align64(bo_size, res->aux.surf.alignment_B);
1147       bo_size = res->aux.offset + res->aux.surf.size_B;
1148    }
1149 
1150    /* Allocate space for the compression control surface. */
1151    if (devinfo->has_aux_map && isl_aux_usage_has_ccs(res->aux.usage)) {
1152       res->aux.comp_ctrl_surf_offset =
1153          (uint32_t)align64(bo_size, INTEL_AUX_MAP_META_ALIGNMENT_B);
1154       bo_size = res->aux.comp_ctrl_surf_offset +
1155                 res->surf.size_B / INTEL_AUX_MAP_MAIN_SIZE_SCALEDOWN;
1156    }
1157 
1158    /* Allocate space for the indirect clear color. */
1159    if (iris_get_aux_clear_color_state_size(screen, res) > 0) {
1160       res->aux.clear_color_offset = align64(bo_size, 64);
1161       bo_size = res->aux.clear_color_offset +
1162                 iris_get_aux_clear_color_state_size(screen, res);
1163    }
1164 
1165    /* The ISL alignment already includes AUX-TT requirements, so no additional
1166     * attention required here :)
1167     */
1168    uint32_t alignment = MAX2(4096, res->surf.alignment_B);
1169    res->bo =
1170       iris_bo_alloc(screen->bufmgr, name, bo_size, alignment, memzone, flags);
1171 
1172    if (!res->bo)
1173       goto fail;
1174 
1175    if (res->aux.usage != ISL_AUX_USAGE_NONE &&
1176        !iris_resource_init_aux_buf(screen, res))
1177       goto fail;
1178 
1179    if (templ->bind & PIPE_BIND_SHARED) {
1180       iris_bo_mark_exported(res->bo);
1181       res->base.is_shared = true;
1182    }
1183 
1184    return &res->base.b;
1185 
1186 fail:
1187    iris_resource_destroy(pscreen, &res->base.b);
1188    return NULL;
1189 }
1190 
1191 static struct pipe_resource *
iris_resource_create_with_modifiers(struct pipe_screen * pscreen,const struct pipe_resource * templ,const uint64_t * modifiers,int modifier_count)1192 iris_resource_create_with_modifiers(struct pipe_screen *pscreen,
1193                                     const struct pipe_resource *templ,
1194                                     const uint64_t *modifiers,
1195                                     int modifier_count)
1196 {
1197    return iris_resource_create_for_image(pscreen, templ, modifiers,
1198                                          modifier_count, 0);
1199 }
1200 
1201 static struct pipe_resource *
iris_resource_create(struct pipe_screen * pscreen,const struct pipe_resource * templ)1202 iris_resource_create(struct pipe_screen *pscreen,
1203                      const struct pipe_resource *templ)
1204 {
1205    if (templ->target == PIPE_BUFFER)
1206       return iris_resource_create_for_buffer(pscreen, templ);
1207    else
1208       return iris_resource_create_with_modifiers(pscreen, templ, NULL, 0);
1209 }
1210 
1211 static uint64_t
tiling_to_modifier(struct iris_bufmgr * bufmgr,uint32_t tiling)1212 tiling_to_modifier(struct iris_bufmgr *bufmgr, uint32_t tiling)
1213 {
1214    if (iris_bufmgr_get_device_info(bufmgr)->kmd_type != INTEL_KMD_TYPE_I915) {
1215       assert(tiling == 0);
1216       return DRM_FORMAT_MOD_LINEAR;
1217    }
1218 
1219    return iris_i915_tiling_to_modifier(tiling);
1220 }
1221 
1222 static struct pipe_resource *
iris_resource_from_user_memory(struct pipe_screen * pscreen,const struct pipe_resource * templ,void * user_memory)1223 iris_resource_from_user_memory(struct pipe_screen *pscreen,
1224                                const struct pipe_resource *templ,
1225                                void *user_memory)
1226 {
1227    if (templ->target != PIPE_BUFFER &&
1228        templ->target != PIPE_TEXTURE_1D &&
1229        templ->target != PIPE_TEXTURE_2D)
1230       return NULL;
1231 
1232    if (templ->array_size > 1)
1233       return NULL;
1234 
1235    struct iris_screen *screen = (struct iris_screen *)pscreen;
1236    struct iris_bufmgr *bufmgr = screen->bufmgr;
1237    struct iris_resource *res = iris_alloc_resource(pscreen, templ);
1238    if (!res)
1239       return NULL;
1240 
1241    size_t res_size = templ->width0;
1242    if (templ->target != PIPE_BUFFER) {
1243       const uint32_t row_pitch_B =
1244          templ->width0 * util_format_get_blocksize(templ->format);
1245       res_size = templ->height0 * row_pitch_B;
1246 
1247       if (!iris_resource_configure_main(screen, res, templ,
1248                                         DRM_FORMAT_MOD_LINEAR,
1249                                         row_pitch_B)) {
1250          iris_resource_destroy(pscreen, &res->base.b);
1251          return NULL;
1252       }
1253       assert(res->surf.size_B <= res_size);
1254    }
1255 
1256    /* The userptr ioctl only works on whole pages.  Because we know that
1257     * things will exist in memory at a page granularity, we can expand the
1258     * range given by the client into the whole number of pages and use an
1259     * offset on the resource to make it looks like it starts at the user's
1260     * pointer.
1261     */
1262    size_t page_size = getpagesize();
1263    assert(util_is_power_of_two_nonzero_uintptr(page_size));
1264    size_t offset = (uintptr_t)user_memory & (page_size - 1);
1265    void *mem_start = (char *)user_memory - offset;
1266    size_t mem_size = offset + res_size;
1267    mem_size = ALIGN_NPOT(mem_size, page_size);
1268 
1269    res->internal_format = templ->format;
1270    res->base.is_user_ptr = true;
1271    res->bo = iris_bo_create_userptr(bufmgr, "user", mem_start, mem_size,
1272                                     IRIS_MEMZONE_OTHER);
1273    res->offset = offset;
1274    if (!res->bo) {
1275       iris_resource_destroy(pscreen, &res->base.b);
1276       return NULL;
1277    }
1278 
1279    util_range_add(&res->base.b, &res->valid_buffer_range, 0, templ->width0);
1280 
1281    return &res->base.b;
1282 }
1283 
1284 static unsigned
get_num_planes(const struct pipe_resource * resource)1285 get_num_planes(const struct pipe_resource *resource)
1286 {
1287    unsigned count = 0;
1288    for (const struct pipe_resource *cur = resource; cur; cur = cur->next)
1289       count++;
1290 
1291    return count;
1292 }
1293 
1294 static unsigned
get_main_plane_for_plane(enum pipe_format format,unsigned plane)1295 get_main_plane_for_plane(enum pipe_format format,
1296                          unsigned plane)
1297 {
1298    if (format == PIPE_FORMAT_NONE) {
1299       /* Created dmabuf resources have this format. */
1300       return 0;
1301    } else if (isl_format_for_pipe_format(format) == ISL_FORMAT_UNSUPPORTED) {
1302       /* This format has been lowered to more planes than are native to it.
1303        * So, compression modifiers are not enabled and the plane index is used
1304        * as-is.
1305        */
1306       return plane;
1307    } else {
1308       unsigned int n_planes = util_format_get_num_planes(format);
1309       return plane % n_planes;
1310    }
1311 }
1312 
1313 static struct pipe_resource *
iris_resource_from_handle(struct pipe_screen * pscreen,const struct pipe_resource * templ,struct winsys_handle * whandle,unsigned usage)1314 iris_resource_from_handle(struct pipe_screen *pscreen,
1315                           const struct pipe_resource *templ,
1316                           struct winsys_handle *whandle,
1317                           unsigned usage)
1318 {
1319    struct iris_screen *screen = (struct iris_screen *)pscreen;
1320    const struct intel_device_info *devinfo = screen->devinfo;
1321    struct iris_bufmgr *bufmgr = screen->bufmgr;
1322 
1323    /* The gallium dri layer creates a pipe resource for each plane specified
1324     * by the format and modifier. Once all planes are present, we will merge
1325     * the separate parameters into the iris_resource(s) for the main plane(s).
1326     * Save the modifier import information now to reconstruct later.
1327     */
1328    struct iris_resource *res = iris_alloc_resource(pscreen, templ);
1329    if (!res)
1330       return NULL;
1331 
1332    switch (whandle->type) {
1333    case WINSYS_HANDLE_TYPE_FD:
1334       res->bo = iris_bo_import_dmabuf(bufmgr, whandle->handle,
1335                                       whandle->modifier);
1336       break;
1337    case WINSYS_HANDLE_TYPE_SHARED:
1338       res->bo = iris_bo_gem_create_from_name(bufmgr, "winsys image",
1339                                              whandle->handle);
1340       break;
1341    default:
1342       unreachable("invalid winsys handle type");
1343    }
1344    if (!res->bo)
1345       goto fail;
1346 
1347    res->offset = whandle->offset;
1348    res->surf.row_pitch_B = whandle->stride;
1349 
1350    if (whandle->plane == 0) {
1351       /* All planes are present. Fill out the main plane resource(s). */
1352       for (unsigned plane = 0; plane < util_resource_num(templ); plane++) {
1353          const unsigned main_plane =
1354             get_main_plane_for_plane(whandle->format, plane);
1355          struct iris_resource *main_res = (struct iris_resource *)
1356             util_resource_at_index(&res->base.b, main_plane);
1357          const struct iris_resource *plane_res = (struct iris_resource *)
1358             util_resource_at_index(&res->base.b, plane);
1359 
1360          if (isl_drm_modifier_plane_is_clear_color(whandle->modifier,
1361                                                    plane)) {
1362             /* Fill out the clear color fields. */
1363             assert(plane_res->bo->size >= plane_res->offset +
1364                    screen->isl_dev.ss.clear_color_state_size);
1365 
1366             iris_bo_reference(plane_res->bo);
1367             main_res->aux.clear_color_bo = plane_res->bo;
1368             main_res->aux.clear_color_offset = plane_res->offset;
1369             main_res->aux.clear_color_unknown = true;
1370          } else if (plane > main_plane) {
1371             /* Fill out some aux surface fields. */
1372             assert(isl_drm_modifier_has_aux(whandle->modifier));
1373             assert(!devinfo->has_flat_ccs);
1374 
1375             iris_bo_reference(plane_res->bo);
1376             res->aux.bo = plane_res->bo;
1377 
1378             if (devinfo->has_aux_map) {
1379                assert(plane_res->surf.row_pitch_B ==
1380                       main_res->surf.row_pitch_B /
1381                       INTEL_AUX_MAP_MAIN_PITCH_SCALEDOWN);
1382                assert(plane_res->bo->size >= plane_res->offset +
1383                       main_res->surf.size_B /
1384                       INTEL_AUX_MAP_MAIN_SIZE_SCALEDOWN);
1385 
1386                main_res->aux.comp_ctrl_surf_offset = plane_res->offset;
1387                map_aux_addresses(screen, main_res, whandle->format,
1388                                  main_plane);
1389             } else {
1390                assert(plane_res->surf.row_pitch_B ==
1391                       main_res->aux.surf.row_pitch_B);
1392                assert(plane_res->bo->size >= plane_res->offset +
1393                       main_res->aux.surf.size_B);
1394 
1395                main_res->aux.offset = plane_res->offset;
1396             }
1397          } else {
1398             /* Fill out fields that are convenient to initialize now. */
1399             assert(plane == main_plane);
1400 
1401             main_res->external_format = whandle->format;
1402 
1403             if (templ->target == PIPE_BUFFER) {
1404                main_res->surf.tiling = ISL_TILING_LINEAR;
1405                return &main_res->base.b;
1406             }
1407 
1408             uint64_t modifier;
1409             if (whandle->modifier == DRM_FORMAT_MOD_INVALID) {
1410                /* We have no modifier; match whatever GEM_GET_TILING says */
1411                uint32_t tiling;
1412                iris_gem_get_tiling(main_res->bo, &tiling);
1413                modifier = tiling_to_modifier(bufmgr, tiling);
1414             } else {
1415                modifier = whandle->modifier;
1416             }
1417 
1418             const bool isl_surf_created_successfully =
1419                iris_resource_configure_main(screen, main_res,
1420                                             &main_res->base.b, modifier,
1421                                             main_res->surf.row_pitch_B);
1422             if (!isl_surf_created_successfully)
1423                goto fail;
1424 
1425             assert(main_res->bo->size >= main_res->offset +
1426                    main_res->surf.size_B);
1427 
1428             if (!iris_resource_configure_aux(screen, main_res))
1429                goto fail;
1430 
1431             if (res->aux.usage != ISL_AUX_USAGE_NONE) {
1432                const enum isl_aux_state aux_state =
1433                   isl_drm_modifier_get_default_aux_state(modifier);
1434                main_res->aux.state =
1435                   create_aux_state_map(main_res, aux_state);
1436                if (!main_res->aux.state)
1437                   goto fail;
1438             }
1439 
1440             /* Add on a clear color BO if needed. */
1441             if (!main_res->mod_info->supports_clear_color &&
1442                 iris_get_aux_clear_color_state_size(screen, main_res) > 0) {
1443                main_res->aux.clear_color_bo =
1444                   iris_bo_alloc(screen->bufmgr, "clear color buffer",
1445                                 screen->isl_dev.ss.clear_color_state_size,
1446                                 64, IRIS_MEMZONE_OTHER, BO_ALLOC_ZEROED);
1447                if (!main_res->aux.clear_color_bo)
1448                   goto fail;
1449             }
1450          }
1451       }
1452    }
1453 
1454    return &res->base.b;
1455 
1456 fail:
1457    iris_resource_destroy(pscreen, &res->base.b);
1458    return NULL;
1459 }
1460 
1461 static struct pipe_resource *
iris_resource_from_memobj(struct pipe_screen * pscreen,const struct pipe_resource * templ,struct pipe_memory_object * pmemobj,uint64_t offset)1462 iris_resource_from_memobj(struct pipe_screen *pscreen,
1463                           const struct pipe_resource *templ,
1464                           struct pipe_memory_object *pmemobj,
1465                           uint64_t offset)
1466 {
1467    struct iris_screen *screen = (struct iris_screen *)pscreen;
1468    struct iris_memory_object *memobj = (struct iris_memory_object *)pmemobj;
1469    struct iris_resource *res = iris_alloc_resource(pscreen, templ);
1470 
1471    if (!res)
1472       return NULL;
1473 
1474    res->bo = memobj->bo;
1475    res->offset = offset;
1476    res->external_format = templ->format;
1477    res->internal_format = templ->format;
1478 
1479    if (templ->flags & PIPE_RESOURCE_FLAG_TEXTURING_MORE_LIKELY) {
1480       UNUSED const bool isl_surf_created_successfully =
1481          iris_resource_configure_main(screen, res, templ, DRM_FORMAT_MOD_INVALID, 0);
1482       assert(isl_surf_created_successfully);
1483    }
1484 
1485    iris_bo_reference(memobj->bo);
1486 
1487    return &res->base.b;
1488 }
1489 
1490 /* Handle combined depth/stencil with memory objects.
1491  *
1492  * This function is modeled after u_transfer_helper_resource_create.
1493  */
1494 static struct pipe_resource *
iris_resource_from_memobj_wrapper(struct pipe_screen * pscreen,const struct pipe_resource * templ,struct pipe_memory_object * pmemobj,uint64_t offset)1495 iris_resource_from_memobj_wrapper(struct pipe_screen *pscreen,
1496                                   const struct pipe_resource *templ,
1497                                   struct pipe_memory_object *pmemobj,
1498                                   uint64_t offset)
1499 {
1500    enum pipe_format format = templ->format;
1501 
1502    /* Normal case, no special handling: */
1503    if (!(util_format_is_depth_and_stencil(format)))
1504       return iris_resource_from_memobj(pscreen, templ, pmemobj, offset);
1505 
1506    struct pipe_resource t = *templ;
1507    t.format = util_format_get_depth_only(format);
1508 
1509    struct pipe_resource *prsc =
1510       iris_resource_from_memobj(pscreen, &t, pmemobj, offset);
1511    if (!prsc)
1512       return NULL;
1513 
1514    struct iris_resource *res = (struct iris_resource *) prsc;
1515 
1516    /* Stencil offset in the buffer without aux. */
1517    uint64_t s_offset = offset +
1518       align64(res->surf.size_B, res->surf.alignment_B);
1519 
1520    prsc->format = format; /* frob the format back to the "external" format */
1521 
1522    t.format = PIPE_FORMAT_S8_UINT;
1523    struct pipe_resource *stencil =
1524       iris_resource_from_memobj(pscreen, &t, pmemobj, s_offset);
1525    if (!stencil) {
1526       iris_resource_destroy(pscreen, prsc);
1527       return NULL;
1528    }
1529 
1530    iris_resource_set_separate_stencil(prsc, stencil);
1531    return prsc;
1532 }
1533 
1534 /**
1535  * Reallocate a (non-external) resource into new storage, copying the data
1536  * and modifying the original resource to point at the new storage.
1537  *
1538  * This is useful for e.g. moving a suballocated internal resource to a
1539  * dedicated allocation that can be exported by itself.
1540  */
1541 static void
iris_reallocate_resource_inplace(struct iris_context * ice,struct iris_resource * old_res,unsigned new_bind_flag)1542 iris_reallocate_resource_inplace(struct iris_context *ice,
1543                                  struct iris_resource *old_res,
1544                                  unsigned new_bind_flag)
1545 {
1546    struct pipe_screen *pscreen = ice->ctx.screen;
1547 
1548    if (iris_bo_is_external(old_res->bo))
1549       return;
1550 
1551    assert(old_res->mod_info == NULL);
1552    assert(old_res->bo == old_res->aux.bo || old_res->aux.bo == NULL);
1553    assert(old_res->bo == old_res->aux.clear_color_bo ||
1554           old_res->aux.clear_color_bo == NULL);
1555    assert(old_res->external_format == PIPE_FORMAT_NONE);
1556 
1557    struct pipe_resource templ = old_res->base.b;
1558    templ.bind |= new_bind_flag;
1559 
1560    struct iris_resource *new_res =
1561       (void *) pscreen->resource_create(pscreen, &templ);
1562 
1563    assert(iris_bo_is_real(new_res->bo));
1564 
1565    struct iris_batch *batch = &ice->batches[IRIS_BATCH_RENDER];
1566 
1567    if (old_res->base.b.target == PIPE_BUFFER) {
1568       struct pipe_box box = (struct pipe_box) {
1569          .width = old_res->base.b.width0,
1570          .height = 1,
1571       };
1572 
1573       iris_copy_region(&ice->blorp, batch, &new_res->base.b, 0, 0, 0, 0,
1574                        &old_res->base.b, 0, &box);
1575    } else {
1576       for (unsigned l = 0; l <= templ.last_level; l++) {
1577          struct pipe_box box = (struct pipe_box) {
1578             .width = u_minify(templ.width0, l),
1579             .height = u_minify(templ.height0, l),
1580             .depth = util_num_layers(&templ, l),
1581          };
1582 
1583          iris_copy_region(&ice->blorp, batch, &new_res->base.b, l, 0, 0, 0,
1584                           &old_res->base.b, l, &box);
1585       }
1586    }
1587 
1588    struct iris_bo *old_bo = old_res->bo;
1589    struct iris_bo *old_aux_bo = old_res->aux.bo;
1590    struct iris_bo *old_clear_color_bo = old_res->aux.clear_color_bo;
1591 
1592    /* Replace the structure fields with the new ones */
1593    old_res->base.b.bind = templ.bind;
1594    old_res->surf = new_res->surf;
1595    old_res->bo = new_res->bo;
1596    old_res->aux.surf = new_res->aux.surf;
1597    old_res->aux.bo = new_res->aux.bo;
1598    old_res->aux.offset = new_res->aux.offset;
1599    old_res->aux.comp_ctrl_surf_offset = new_res->aux.comp_ctrl_surf_offset;
1600    old_res->aux.clear_color_bo = new_res->aux.clear_color_bo;
1601    old_res->aux.clear_color_offset = new_res->aux.clear_color_offset;
1602    old_res->aux.usage = new_res->aux.usage;
1603 
1604    if (new_res->aux.state) {
1605       assert(old_res->aux.state);
1606       for (unsigned l = 0; l <= templ.last_level; l++) {
1607          unsigned layers = util_num_layers(&templ, l);
1608          for (unsigned z = 0; z < layers; z++) {
1609             enum isl_aux_state aux =
1610                iris_resource_get_aux_state(new_res, l, z);
1611             iris_resource_set_aux_state(ice, old_res, l, z, 1, aux);
1612          }
1613       }
1614    }
1615 
1616    /* old_res now points at the new BOs, make new_res point at the old ones
1617     * so they'll be freed when we unreference the resource below.
1618     */
1619    new_res->bo = old_bo;
1620    new_res->aux.bo = old_aux_bo;
1621    new_res->aux.clear_color_bo = old_clear_color_bo;
1622 
1623    pipe_resource_reference((struct pipe_resource **)&new_res, NULL);
1624 }
1625 
1626 static void
iris_flush_resource(struct pipe_context * ctx,struct pipe_resource * resource)1627 iris_flush_resource(struct pipe_context *ctx, struct pipe_resource *resource)
1628 {
1629    struct iris_context *ice = (struct iris_context *)ctx;
1630    struct iris_resource *res = (void *) resource;
1631    const struct isl_drm_modifier_info *mod = res->mod_info;
1632    bool newly_external = false;
1633 
1634    /* flush_resource() may be used to prepare an image for sharing externally
1635     * with other clients (e.g. via eglCreateImage).  To account for this, we
1636     * make sure to eliminate suballocation and any compression that a consumer
1637     * wouldn't know how to handle.
1638     */
1639    if (!iris_bo_is_real(res->bo)) {
1640       assert(!(res->base.b.bind & PIPE_BIND_SHARED));
1641       iris_reallocate_resource_inplace(ice, res, PIPE_BIND_SHARED);
1642       assert(res->base.b.bind & PIPE_BIND_SHARED);
1643       newly_external = true;
1644    }
1645 
1646    iris_resource_prepare_access(ice, res,
1647                                 0, INTEL_REMAINING_LEVELS,
1648                                 0, INTEL_REMAINING_LAYERS,
1649                                 mod ? res->aux.usage : ISL_AUX_USAGE_NONE,
1650                                 mod ? mod->supports_clear_color : false);
1651 
1652    bool disable_aux = !res->mod_info && res->aux.usage != ISL_AUX_USAGE_NONE;
1653 
1654    if (newly_external || disable_aux) {
1655       iris_foreach_batch(ice, batch) {
1656          if (iris_batch_references(batch, res->bo))
1657             iris_batch_flush(batch);
1658       }
1659    }
1660 
1661    if (disable_aux)
1662       iris_resource_disable_aux(res);
1663 }
1664 
1665 static void
iris_resource_disable_aux_on_first_query(struct pipe_resource * resource,unsigned usage)1666 iris_resource_disable_aux_on_first_query(struct pipe_resource *resource,
1667                                          unsigned usage)
1668 {
1669    struct iris_resource *res = (struct iris_resource *)resource;
1670    bool mod_with_aux =
1671       res->mod_info && isl_drm_modifier_has_aux(res->mod_info->modifier);
1672 
1673    /* Disable aux usage if explicit flush not set and this is the first time
1674     * we are dealing with this resource and the resource was not created with
1675     * a modifier with aux.
1676     */
1677    if (!mod_with_aux &&
1678       (!(usage & PIPE_HANDLE_USAGE_EXPLICIT_FLUSH) && res->aux.usage != 0) &&
1679        p_atomic_read(&resource->reference.count) == 1) {
1680          iris_resource_disable_aux(res);
1681    }
1682 }
1683 
1684 static bool
iris_resource_get_param(struct pipe_screen * pscreen,struct pipe_context * ctx,struct pipe_resource * resource,unsigned plane,unsigned layer,unsigned level,enum pipe_resource_param param,unsigned handle_usage,uint64_t * value)1685 iris_resource_get_param(struct pipe_screen *pscreen,
1686                         struct pipe_context *ctx,
1687                         struct pipe_resource *resource,
1688                         unsigned plane,
1689                         unsigned layer,
1690                         unsigned level,
1691                         enum pipe_resource_param param,
1692                         unsigned handle_usage,
1693                         uint64_t *value)
1694 {
1695    struct iris_screen *screen = (struct iris_screen *)pscreen;
1696    struct iris_resource *base_res = (struct iris_resource *)resource;
1697    unsigned main_plane = get_main_plane_for_plane(base_res->external_format,
1698                                                   plane);
1699    struct iris_resource *res =
1700       (struct iris_resource *)util_resource_at_index(resource, main_plane);
1701    assert(res);
1702 
1703    bool mod_with_aux =
1704       res->mod_info && isl_drm_modifier_has_aux(res->mod_info->modifier);
1705    bool wants_aux = mod_with_aux && plane != main_plane;
1706    bool wants_cc = mod_with_aux &&
1707       isl_drm_modifier_plane_is_clear_color(res->mod_info->modifier, plane);
1708    bool result;
1709    unsigned handle;
1710 
1711    iris_resource_disable_aux_on_first_query(resource, handle_usage);
1712 
1713    struct iris_bo *bo = wants_cc ? res->aux.clear_color_bo :
1714                         wants_aux ? res->aux.bo : res->bo;
1715 
1716    assert(iris_bo_is_real(bo));
1717 
1718    switch (param) {
1719    case PIPE_RESOURCE_PARAM_NPLANES:
1720       if (mod_with_aux) {
1721          *value = iris_get_dmabuf_modifier_planes(pscreen,
1722                                                   res->mod_info->modifier,
1723                                                   res->external_format);
1724       } else {
1725          *value = get_num_planes(&res->base.b);
1726       }
1727       return true;
1728    case PIPE_RESOURCE_PARAM_STRIDE:
1729       if (wants_cc) {
1730          *value = ISL_DRM_CC_PLANE_PITCH_B;
1731       } else if (wants_aux) {
1732          *value = screen->devinfo->has_aux_map ?
1733                   res->surf.row_pitch_B / INTEL_AUX_MAP_MAIN_PITCH_SCALEDOWN :
1734                   res->aux.surf.row_pitch_B;
1735       } else {
1736          *value = res->surf.row_pitch_B;
1737       }
1738 
1739       /* Mesa's implementation of eglCreateImage rejects strides of zero (see
1740        * dri2_check_dma_buf_attribs). Ensure we return a non-zero stride as
1741        * this value may be queried from GBM and passed into EGL.
1742        *
1743        * We make an exception for buffers. For OpenCL gl_sharing we have to
1744        * support exporting buffers, for which we report a stride of 0 here.
1745        */
1746       assert(*value != 0 || resource->target == PIPE_BUFFER);
1747 
1748       return true;
1749    case PIPE_RESOURCE_PARAM_OFFSET:
1750       if (wants_cc) {
1751          *value = res->aux.clear_color_offset;
1752       } else if (wants_aux) {
1753          *value = screen->devinfo->has_aux_map ?
1754                   res->aux.comp_ctrl_surf_offset :
1755                   res->aux.offset;
1756       } else {
1757          *value = res->offset;
1758       }
1759       return true;
1760    case PIPE_RESOURCE_PARAM_MODIFIER:
1761       if (res->mod_info) {
1762          *value = res->mod_info->modifier;
1763       } else {
1764          /* We restrict ourselves to modifiers without CCS for several
1765           * reasons:
1766           *
1767           *    - Mesa's implementation of EGL_MESA_image_dma_buf_export
1768           *      currently only exports a single plane (see
1769           *      dri2_export_dma_buf_image_mesa), but for some modifiers,
1770           *      CCS exists in a second plane.
1771           *
1772           *    - Even if we returned CCS modifiers, iris currently
1773           *      resolves away compression during the export/flushing process
1774           *      (see iris_flush_resource). So, only uncompressed data is
1775           *      exposed anyways.
1776           */
1777          switch (res->surf.tiling) {
1778          case ISL_TILING_4:      *value = I915_FORMAT_MOD_4_TILED; break;
1779          case ISL_TILING_Y0:     *value = I915_FORMAT_MOD_Y_TILED; break;
1780          case ISL_TILING_X:      *value = I915_FORMAT_MOD_X_TILED; break;
1781          case ISL_TILING_LINEAR: *value =  DRM_FORMAT_MOD_LINEAR;  break;
1782          default:
1783             assert("no modifier mapped for resource's tiling");
1784             return false;
1785          }
1786       }
1787       return true;
1788    case PIPE_RESOURCE_PARAM_HANDLE_TYPE_SHARED:
1789       if (!wants_aux)
1790          iris_gem_set_tiling(bo, &res->surf);
1791 
1792       result = iris_bo_flink(bo, &handle) == 0;
1793       if (result)
1794          *value = handle;
1795       return result;
1796    case PIPE_RESOURCE_PARAM_HANDLE_TYPE_KMS: {
1797       if (!wants_aux)
1798          iris_gem_set_tiling(bo, &res->surf);
1799 
1800       /* Because we share the same drm file across multiple iris_screen, when
1801        * we export a GEM handle we must make sure it is valid in the DRM file
1802        * descriptor the caller is using (this is the FD given at screen
1803        * creation).
1804        */
1805       uint32_t handle;
1806       if (iris_bo_export_gem_handle_for_device(bo, screen->winsys_fd, &handle))
1807          return false;
1808       *value = handle;
1809       return true;
1810    }
1811 
1812    case PIPE_RESOURCE_PARAM_HANDLE_TYPE_FD:
1813       if (!wants_aux)
1814          iris_gem_set_tiling(bo, &res->surf);
1815 
1816       result = iris_bo_export_dmabuf(bo, (int *) &handle) == 0;
1817       if (result)
1818          *value = handle;
1819       return result;
1820    default:
1821       return false;
1822    }
1823 }
1824 
1825 static bool
iris_resource_get_handle(struct pipe_screen * pscreen,struct pipe_context * ctx,struct pipe_resource * resource,struct winsys_handle * whandle,unsigned usage)1826 iris_resource_get_handle(struct pipe_screen *pscreen,
1827                          struct pipe_context *ctx,
1828                          struct pipe_resource *resource,
1829                          struct winsys_handle *whandle,
1830                          unsigned usage)
1831 {
1832    struct iris_screen *screen = (struct iris_screen *) pscreen;
1833    struct iris_resource *res = (struct iris_resource *)resource;
1834    bool mod_with_aux =
1835       res->mod_info && isl_drm_modifier_has_aux(res->mod_info->modifier);
1836 
1837    iris_resource_disable_aux_on_first_query(resource, usage);
1838 
1839    assert(iris_bo_is_real(res->bo));
1840 
1841    struct iris_bo *bo;
1842    if (res->mod_info &&
1843        isl_drm_modifier_plane_is_clear_color(res->mod_info->modifier,
1844                                              whandle->plane)) {
1845       bo = res->aux.clear_color_bo;
1846    } else if (mod_with_aux && whandle->plane > 0) {
1847       bo = res->aux.bo;
1848    } else {
1849       bo = res->bo;
1850    }
1851 
1852    uint64_t stride;
1853    iris_resource_get_param(pscreen, ctx, resource, whandle->plane, 0, 0,
1854                            PIPE_RESOURCE_PARAM_STRIDE, usage, &stride);
1855 
1856    uint64_t offset;
1857    iris_resource_get_param(pscreen, ctx, resource, whandle->plane, 0, 0,
1858                            PIPE_RESOURCE_PARAM_OFFSET, usage, &offset);
1859 
1860    uint64_t modifier;
1861    iris_resource_get_param(pscreen, ctx, resource, whandle->plane, 0, 0,
1862                            PIPE_RESOURCE_PARAM_MODIFIER, usage, &modifier);
1863 
1864    whandle->stride = stride;
1865    whandle->offset = offset;
1866    whandle->modifier = modifier;
1867    whandle->format = res->external_format;
1868 
1869 #ifndef NDEBUG
1870    enum isl_aux_usage allowed_usage =
1871       (usage & PIPE_HANDLE_USAGE_EXPLICIT_FLUSH) || mod_with_aux ?
1872       res->aux.usage : ISL_AUX_USAGE_NONE;
1873 
1874    if (res->aux.usage != allowed_usage) {
1875       enum isl_aux_state aux_state = iris_resource_get_aux_state(res, 0, 0);
1876       assert(aux_state == ISL_AUX_STATE_RESOLVED ||
1877              aux_state == ISL_AUX_STATE_PASS_THROUGH);
1878    }
1879 #endif
1880 
1881    switch (whandle->type) {
1882    case WINSYS_HANDLE_TYPE_SHARED:
1883       iris_gem_set_tiling(bo, &res->surf);
1884       return iris_bo_flink(bo, &whandle->handle) == 0;
1885    case WINSYS_HANDLE_TYPE_KMS: {
1886       iris_gem_set_tiling(bo, &res->surf);
1887 
1888       /* Because we share the same drm file across multiple iris_screen, when
1889        * we export a GEM handle we must make sure it is valid in the DRM file
1890        * descriptor the caller is using (this is the FD given at screen
1891        * creation).
1892        */
1893       uint32_t handle;
1894       if (iris_bo_export_gem_handle_for_device(bo, screen->winsys_fd, &handle))
1895          return false;
1896       whandle->handle = handle;
1897       return true;
1898    }
1899    case WINSYS_HANDLE_TYPE_FD:
1900       iris_gem_set_tiling(bo, &res->surf);
1901       return iris_bo_export_dmabuf(bo, (int *) &whandle->handle) == 0;
1902    }
1903 
1904    return false;
1905 }
1906 
1907 static bool
resource_is_busy(struct iris_context * ice,struct iris_resource * res)1908 resource_is_busy(struct iris_context *ice,
1909                  struct iris_resource *res)
1910 {
1911    bool busy = iris_bo_busy(res->bo);
1912 
1913    iris_foreach_batch(ice, batch)
1914       busy |= iris_batch_references(batch, res->bo);
1915 
1916    return busy;
1917 }
1918 
1919 void
iris_replace_buffer_storage(struct pipe_context * ctx,struct pipe_resource * p_dst,struct pipe_resource * p_src,unsigned num_rebinds,uint32_t rebind_mask,uint32_t delete_buffer_id)1920 iris_replace_buffer_storage(struct pipe_context *ctx,
1921                             struct pipe_resource *p_dst,
1922                             struct pipe_resource *p_src,
1923                             unsigned num_rebinds,
1924                             uint32_t rebind_mask,
1925                             uint32_t delete_buffer_id)
1926 {
1927    struct iris_screen *screen = (void *) ctx->screen;
1928    struct iris_context *ice = (void *) ctx;
1929    struct iris_resource *dst = (void *) p_dst;
1930    struct iris_resource *src = (void *) p_src;
1931 
1932    assert(memcmp(&dst->surf, &src->surf, sizeof(dst->surf)) == 0);
1933 
1934    struct iris_bo *old_bo = dst->bo;
1935 
1936    /* Swap out the backing storage */
1937    iris_bo_reference(src->bo);
1938    dst->bo = src->bo;
1939 
1940    /* Rebind the buffer, replacing any state referring to the old BO's
1941     * address, and marking state dirty so it's reemitted.
1942     */
1943    screen->vtbl.rebind_buffer(ice, dst);
1944 
1945    iris_bo_unreference(old_bo);
1946 }
1947 
1948 /**
1949  * Discard a buffer's contents and replace it's backing storage with a
1950  * fresh, idle buffer if necessary.
1951  *
1952  * Returns true if the storage can be considered idle.
1953  */
1954 static bool
iris_invalidate_buffer(struct iris_context * ice,struct iris_resource * res)1955 iris_invalidate_buffer(struct iris_context *ice, struct iris_resource *res)
1956 {
1957    struct iris_screen *screen = (void *) ice->ctx.screen;
1958 
1959    if (res->base.b.target != PIPE_BUFFER)
1960       return false;
1961 
1962    /* If it's already invalidated, don't bother doing anything.
1963     * We consider the storage to be idle, because either it was freshly
1964     * allocated (and not busy), or a previous call here was what cleared
1965     * the range, and that call replaced the storage with an idle buffer.
1966     */
1967    if (res->valid_buffer_range.start > res->valid_buffer_range.end)
1968       return true;
1969 
1970    if (!resource_is_busy(ice, res)) {
1971       /* The resource is idle, so just mark that it contains no data and
1972        * keep using the same underlying buffer object.
1973        */
1974       util_range_set_empty(&res->valid_buffer_range);
1975       return true;
1976    }
1977 
1978    /* Otherwise, try and replace the backing storage with a new BO. */
1979 
1980    /* We can't reallocate memory we didn't allocate in the first place. */
1981    if (res->bo->gem_handle && res->bo->real.userptr)
1982       return false;
1983 
1984    /* Nor can we allocate buffers we imported or exported. */
1985    if (iris_bo_is_external(res->bo))
1986       return false;
1987 
1988    struct iris_bo *old_bo = res->bo;
1989    unsigned flags = old_bo->real.protected ? BO_ALLOC_PROTECTED : BO_ALLOC_PLAIN;
1990    struct iris_bo *new_bo =
1991       iris_bo_alloc(screen->bufmgr, res->bo->name, res->base.b.width0,
1992                     iris_buffer_alignment(res->base.b.width0),
1993                     iris_memzone_for_address(old_bo->address),
1994                     flags);
1995    if (!new_bo)
1996       return false;
1997 
1998    /* Swap out the backing storage */
1999    res->bo = new_bo;
2000 
2001    /* Rebind the buffer, replacing any state referring to the old BO's
2002     * address, and marking state dirty so it's reemitted.
2003     */
2004    screen->vtbl.rebind_buffer(ice, res);
2005 
2006    util_range_set_empty(&res->valid_buffer_range);
2007 
2008    iris_bo_unreference(old_bo);
2009 
2010    /* The new buffer is idle. */
2011    return true;
2012 }
2013 
2014 static void
iris_invalidate_resource(struct pipe_context * ctx,struct pipe_resource * resource)2015 iris_invalidate_resource(struct pipe_context *ctx,
2016                          struct pipe_resource *resource)
2017 {
2018    struct iris_context *ice = (void *) ctx;
2019    struct iris_resource *res = (void *) resource;
2020 
2021    iris_invalidate_buffer(ice, res);
2022 }
2023 
2024 static void
iris_flush_staging_region(struct pipe_transfer * xfer,const struct pipe_box * flush_box)2025 iris_flush_staging_region(struct pipe_transfer *xfer,
2026                           const struct pipe_box *flush_box)
2027 {
2028    if (!(xfer->usage & PIPE_MAP_WRITE))
2029       return;
2030 
2031    struct iris_transfer *map = (void *) xfer;
2032 
2033    struct pipe_box src_box = *flush_box;
2034 
2035    /* Account for extra alignment padding in staging buffer */
2036    if (xfer->resource->target == PIPE_BUFFER)
2037       src_box.x += xfer->box.x % IRIS_MAP_BUFFER_ALIGNMENT;
2038 
2039    struct pipe_box dst_box = (struct pipe_box) {
2040       .x = xfer->box.x + flush_box->x,
2041       .y = xfer->box.y + flush_box->y,
2042       .z = xfer->box.z + flush_box->z,
2043       .width = flush_box->width,
2044       .height = flush_box->height,
2045       .depth = flush_box->depth,
2046    };
2047 
2048    iris_copy_region(map->blorp, map->batch, xfer->resource, xfer->level,
2049                     dst_box.x, dst_box.y, dst_box.z, map->staging, 0,
2050                     &src_box);
2051 }
2052 
2053 static void
iris_unmap_copy_region(struct iris_transfer * map)2054 iris_unmap_copy_region(struct iris_transfer *map)
2055 {
2056    iris_resource_destroy(map->staging->screen, map->staging);
2057 
2058    map->ptr = NULL;
2059 }
2060 
2061 static void
iris_map_copy_region(struct iris_transfer * map)2062 iris_map_copy_region(struct iris_transfer *map)
2063 {
2064    struct pipe_screen *pscreen = &map->batch->screen->base;
2065    struct pipe_transfer *xfer = &map->base.b;
2066    struct pipe_box *box = &xfer->box;
2067    struct iris_resource *res = (void *) xfer->resource;
2068 
2069    unsigned extra = xfer->resource->target == PIPE_BUFFER ?
2070                     box->x % IRIS_MAP_BUFFER_ALIGNMENT : 0;
2071 
2072    struct pipe_resource templ = (struct pipe_resource) {
2073       .usage = PIPE_USAGE_STAGING,
2074       .width0 = box->width + extra,
2075       .height0 = box->height,
2076       .depth0 = 1,
2077       .nr_samples = xfer->resource->nr_samples,
2078       .nr_storage_samples = xfer->resource->nr_storage_samples,
2079       .array_size = box->depth,
2080       .format = res->internal_format,
2081    };
2082 
2083    if (xfer->resource->target == PIPE_BUFFER) {
2084       templ.target = PIPE_BUFFER;
2085       map->staging = iris_resource_create_for_buffer(pscreen, &templ);
2086    } else {
2087       templ.target = templ.array_size > 1 ? PIPE_TEXTURE_2D_ARRAY
2088                                           : PIPE_TEXTURE_2D;
2089 
2090       unsigned row_pitch_B = 0;
2091 
2092 #if DETECT_OS_ANDROID
2093       /* Staging buffers for stall-avoidance blits don't always have the
2094        * same restrictions on stride as the original buffer.  For example,
2095        * the original buffer may be used for scanout, while the staging
2096        * buffer will not be.  So we may compute a smaller stride for the
2097        * staging buffer than the original.
2098        *
2099        * Normally, this is good, as it saves memory.  Unfortunately, for
2100        * Android, gbm_gralloc incorrectly asserts that the stride returned
2101        * by gbm_bo_map() must equal the result of gbm_bo_get_stride(),
2102        * which simply isn't always the case.
2103        *
2104        * Because gralloc is unlikely to be fixed, we hack around it in iris
2105        * by forcing the staging buffer to have a matching stride.
2106        */
2107       if (iris_bo_is_external(res->bo))
2108          row_pitch_B = res->surf.row_pitch_B;
2109 #endif
2110 
2111       map->staging =
2112          iris_resource_create_for_image(pscreen, &templ, NULL, 0, row_pitch_B);
2113    }
2114 
2115    /* If we fail to create a staging resource, the caller will fallback
2116     * to mapping directly on the CPU.
2117     */
2118    if (!map->staging)
2119       return;
2120 
2121    if (templ.target != PIPE_BUFFER) {
2122       struct isl_surf *surf = &((struct iris_resource *) map->staging)->surf;
2123       xfer->stride = isl_surf_get_row_pitch_B(surf);
2124       xfer->layer_stride = isl_surf_get_array_pitch(surf);
2125    }
2126 
2127    if ((xfer->usage & PIPE_MAP_READ) ||
2128        (res->base.b.target == PIPE_BUFFER &&
2129         !(xfer->usage & PIPE_MAP_DISCARD_RANGE))) {
2130       iris_copy_region(map->blorp, map->batch, map->staging, 0, extra, 0, 0,
2131                        xfer->resource, xfer->level, box);
2132       /* Ensure writes to the staging BO land before we map it below. */
2133       iris_emit_pipe_control_flush(map->batch,
2134                                    "transfer read: flush before mapping",
2135                                    PIPE_CONTROL_RENDER_TARGET_FLUSH |
2136                                    PIPE_CONTROL_TILE_CACHE_FLUSH |
2137                                    PIPE_CONTROL_CS_STALL);
2138    }
2139 
2140    struct iris_bo *staging_bo = iris_resource_bo(map->staging);
2141 
2142    if (iris_batch_references(map->batch, staging_bo))
2143       iris_batch_flush(map->batch);
2144 
2145    assert(((struct iris_resource *)map->staging)->offset == 0);
2146    map->ptr =
2147       iris_bo_map(map->dbg, staging_bo, xfer->usage & MAP_FLAGS) + extra;
2148 
2149    map->unmap = iris_unmap_copy_region;
2150 }
2151 
2152 static void
get_image_offset_el(const struct isl_surf * surf,unsigned level,unsigned z,unsigned * out_x0_el,unsigned * out_y0_el)2153 get_image_offset_el(const struct isl_surf *surf, unsigned level, unsigned z,
2154                     unsigned *out_x0_el, unsigned *out_y0_el)
2155 {
2156    ASSERTED uint32_t z0_el, a0_el;
2157    if (surf->dim == ISL_SURF_DIM_3D) {
2158       isl_surf_get_image_offset_el(surf, level, 0, z,
2159                                    out_x0_el, out_y0_el, &z0_el, &a0_el);
2160    } else {
2161       isl_surf_get_image_offset_el(surf, level, z, 0,
2162                                    out_x0_el, out_y0_el, &z0_el, &a0_el);
2163    }
2164    assert(z0_el == 0 && a0_el == 0);
2165 }
2166 
2167 /**
2168  * Get pointer offset into stencil buffer.
2169  *
2170  * The stencil buffer is W tiled. Since the GTT is incapable of W fencing, we
2171  * must decode the tile's layout in software.
2172  *
2173  * See
2174  *   - PRM, 2011 Sandy Bridge, Volume 1, Part 2, Section 4.5.2.1 W-Major Tile
2175  *     Format.
2176  *   - PRM, 2011 Sandy Bridge, Volume 1, Part 2, Section 4.5.3 Tiling Algorithm
2177  *
2178  * Even though the returned offset is always positive, the return type is
2179  * signed due to
2180  *    commit e8b1c6d6f55f5be3bef25084fdd8b6127517e137
2181  *    mesa: Fix return type of  _mesa_get_format_bytes() (#37351)
2182  */
2183 static intptr_t
s8_offset(uint32_t stride,uint32_t x,uint32_t y)2184 s8_offset(uint32_t stride, uint32_t x, uint32_t y)
2185 {
2186    uint32_t tile_size = 4096;
2187    uint32_t tile_width = 64;
2188    uint32_t tile_height = 64;
2189    uint32_t row_size = 64 * stride / 2; /* Two rows are interleaved. */
2190 
2191    uint32_t tile_x = x / tile_width;
2192    uint32_t tile_y = y / tile_height;
2193 
2194    /* The byte's address relative to the tile's base addres. */
2195    uint32_t byte_x = x % tile_width;
2196    uint32_t byte_y = y % tile_height;
2197 
2198    uintptr_t u = tile_y * row_size
2199                + tile_x * tile_size
2200                + 512 * (byte_x / 8)
2201                +  64 * (byte_y / 8)
2202                +  32 * ((byte_y / 4) % 2)
2203                +  16 * ((byte_x / 4) % 2)
2204                +   8 * ((byte_y / 2) % 2)
2205                +   4 * ((byte_x / 2) % 2)
2206                +   2 * (byte_y % 2)
2207                +   1 * (byte_x % 2);
2208 
2209    return u;
2210 }
2211 
2212 static void
iris_unmap_s8(struct iris_transfer * map)2213 iris_unmap_s8(struct iris_transfer *map)
2214 {
2215    struct pipe_transfer *xfer = &map->base.b;
2216    const struct pipe_box *box = &xfer->box;
2217    struct iris_resource *res = (struct iris_resource *) xfer->resource;
2218    struct isl_surf *surf = &res->surf;
2219 
2220    if (xfer->usage & PIPE_MAP_WRITE) {
2221       uint8_t *untiled_s8_map = map->ptr;
2222       uint8_t *tiled_s8_map = res->offset +
2223          iris_bo_map(map->dbg, res->bo, (xfer->usage | MAP_RAW) & MAP_FLAGS);
2224 
2225       for (int s = 0; s < box->depth; s++) {
2226          unsigned x0_el, y0_el;
2227          get_image_offset_el(surf, xfer->level, box->z + s, &x0_el, &y0_el);
2228 
2229          for (uint32_t y = 0; y < box->height; y++) {
2230             for (uint32_t x = 0; x < box->width; x++) {
2231                ptrdiff_t offset = s8_offset(surf->row_pitch_B,
2232                                             x0_el + box->x + x,
2233                                             y0_el + box->y + y);
2234                tiled_s8_map[offset] =
2235                   untiled_s8_map[s * xfer->layer_stride + y * xfer->stride + x];
2236             }
2237          }
2238       }
2239    }
2240 
2241    free(map->buffer);
2242 }
2243 
2244 static void
iris_map_s8(struct iris_transfer * map)2245 iris_map_s8(struct iris_transfer *map)
2246 {
2247    struct pipe_transfer *xfer = &map->base.b;
2248    const struct pipe_box *box = &xfer->box;
2249    struct iris_resource *res = (struct iris_resource *) xfer->resource;
2250    struct isl_surf *surf = &res->surf;
2251 
2252    xfer->stride = surf->row_pitch_B;
2253    xfer->layer_stride = xfer->stride * box->height;
2254 
2255    /* The tiling and detiling functions require that the linear buffer has
2256     * a 16-byte alignment (that is, its `x0` is 16-byte aligned).  Here we
2257     * over-allocate the linear buffer to get the proper alignment.
2258     */
2259    map->buffer = map->ptr = malloc(xfer->layer_stride * box->depth);
2260    assert(map->buffer);
2261 
2262    /* One of either READ_BIT or WRITE_BIT or both is set.  READ_BIT implies no
2263     * INVALIDATE_RANGE_BIT.  WRITE_BIT needs the original values read in unless
2264     * invalidate is set, since we'll be writing the whole rectangle from our
2265     * temporary buffer back out.
2266     */
2267    if (xfer->usage & PIPE_MAP_READ) {
2268       uint8_t *untiled_s8_map = map->ptr;
2269       uint8_t *tiled_s8_map = res->offset +
2270          iris_bo_map(map->dbg, res->bo, (xfer->usage | MAP_RAW) & MAP_FLAGS);
2271 
2272       for (int s = 0; s < box->depth; s++) {
2273          unsigned x0_el, y0_el;
2274          get_image_offset_el(surf, xfer->level, box->z + s, &x0_el, &y0_el);
2275 
2276          for (uint32_t y = 0; y < box->height; y++) {
2277             for (uint32_t x = 0; x < box->width; x++) {
2278                ptrdiff_t offset = s8_offset(surf->row_pitch_B,
2279                                             x0_el + box->x + x,
2280                                             y0_el + box->y + y);
2281                untiled_s8_map[s * xfer->layer_stride + y * xfer->stride + x] =
2282                   tiled_s8_map[offset];
2283             }
2284          }
2285       }
2286    }
2287 
2288    map->unmap = iris_unmap_s8;
2289 }
2290 
2291 /* Compute extent parameters for use with tiled_memcpy functions.
2292  * xs are in units of bytes and ys are in units of strides.
2293  */
2294 static inline void
tile_extents(const struct isl_surf * surf,const struct pipe_box * box,unsigned level,int z,unsigned * x1_B,unsigned * x2_B,unsigned * y1_el,unsigned * y2_el)2295 tile_extents(const struct isl_surf *surf,
2296              const struct pipe_box *box,
2297              unsigned level, int z,
2298              unsigned *x1_B, unsigned *x2_B,
2299              unsigned *y1_el, unsigned *y2_el)
2300 {
2301    const struct isl_format_layout *fmtl = isl_format_get_layout(surf->format);
2302    const unsigned cpp = fmtl->bpb / 8;
2303 
2304    assert(box->x % fmtl->bw == 0);
2305    assert(box->y % fmtl->bh == 0);
2306 
2307    unsigned x0_el, y0_el;
2308    get_image_offset_el(surf, level, box->z + z, &x0_el, &y0_el);
2309 
2310    *x1_B = (box->x / fmtl->bw + x0_el) * cpp;
2311    *y1_el = box->y / fmtl->bh + y0_el;
2312    *x2_B = (DIV_ROUND_UP(box->x + box->width, fmtl->bw) + x0_el) * cpp;
2313    *y2_el = DIV_ROUND_UP(box->y + box->height, fmtl->bh) + y0_el;
2314 }
2315 
2316 static void
iris_unmap_tiled_memcpy(struct iris_transfer * map)2317 iris_unmap_tiled_memcpy(struct iris_transfer *map)
2318 {
2319    struct pipe_transfer *xfer = &map->base.b;
2320    const struct pipe_box *box = &xfer->box;
2321    struct iris_resource *res = (struct iris_resource *) xfer->resource;
2322    struct isl_surf *surf = &res->surf;
2323 
2324    const bool has_swizzling = false;
2325 
2326    if (xfer->usage & PIPE_MAP_WRITE) {
2327       char *dst = res->offset +
2328          iris_bo_map(map->dbg, res->bo, (xfer->usage | MAP_RAW) & MAP_FLAGS);
2329 
2330       for (int s = 0; s < box->depth; s++) {
2331          unsigned x1, x2, y1, y2;
2332          tile_extents(surf, box, xfer->level, s, &x1, &x2, &y1, &y2);
2333 
2334          void *ptr = map->ptr + s * xfer->layer_stride;
2335 
2336          isl_memcpy_linear_to_tiled(x1, x2, y1, y2, dst, ptr,
2337                                     surf->row_pitch_B, xfer->stride,
2338                                     has_swizzling, surf->tiling, ISL_MEMCPY);
2339       }
2340    }
2341    os_free_aligned(map->buffer);
2342    map->buffer = map->ptr = NULL;
2343 }
2344 
2345 static void
iris_map_tiled_memcpy(struct iris_transfer * map)2346 iris_map_tiled_memcpy(struct iris_transfer *map)
2347 {
2348    struct pipe_transfer *xfer = &map->base.b;
2349    const struct pipe_box *box = &xfer->box;
2350    struct iris_resource *res = (struct iris_resource *) xfer->resource;
2351    struct isl_surf *surf = &res->surf;
2352 
2353    xfer->stride = ALIGN(surf->row_pitch_B, 16);
2354    xfer->layer_stride = xfer->stride * box->height;
2355 
2356    unsigned x1, x2, y1, y2;
2357    tile_extents(surf, box, xfer->level, 0, &x1, &x2, &y1, &y2);
2358 
2359    /* The tiling and detiling functions require that the linear buffer has
2360     * a 16-byte alignment (that is, its `x0` is 16-byte aligned).  Here we
2361     * over-allocate the linear buffer to get the proper alignment.
2362     */
2363    map->buffer =
2364       os_malloc_aligned(xfer->layer_stride * box->depth, 16);
2365    assert(map->buffer);
2366    map->ptr = (char *)map->buffer + (x1 & 0xf);
2367 
2368    const bool has_swizzling = false;
2369 
2370    if (xfer->usage & PIPE_MAP_READ) {
2371       char *src = res->offset +
2372          iris_bo_map(map->dbg, res->bo, (xfer->usage | MAP_RAW) & MAP_FLAGS);
2373 
2374       for (int s = 0; s < box->depth; s++) {
2375          unsigned x1, x2, y1, y2;
2376          tile_extents(surf, box, xfer->level, s, &x1, &x2, &y1, &y2);
2377 
2378          /* Use 's' rather than 'box->z' to rebase the first slice to 0. */
2379          void *ptr = map->ptr + s * xfer->layer_stride;
2380 
2381          isl_memcpy_tiled_to_linear(x1, x2, y1, y2, ptr, src, xfer->stride,
2382                                     surf->row_pitch_B, has_swizzling,
2383                                     surf->tiling,
2384 #if defined(USE_SSE41)
2385                                     util_get_cpu_caps()->has_sse4_1 ?
2386                                     ISL_MEMCPY_STREAMING_LOAD :
2387 #endif
2388                                     ISL_MEMCPY);
2389       }
2390    }
2391 
2392    map->unmap = iris_unmap_tiled_memcpy;
2393 }
2394 
2395 static void
iris_map_direct(struct iris_transfer * map)2396 iris_map_direct(struct iris_transfer *map)
2397 {
2398    struct pipe_transfer *xfer = &map->base.b;
2399    struct pipe_box *box = &xfer->box;
2400    struct iris_resource *res = (struct iris_resource *) xfer->resource;
2401 
2402    void *ptr = res->offset +
2403       iris_bo_map(map->dbg, res->bo, xfer->usage & MAP_FLAGS);
2404 
2405    if (res->base.b.target == PIPE_BUFFER) {
2406       xfer->stride = 0;
2407       xfer->layer_stride = 0;
2408 
2409       map->ptr = ptr + box->x;
2410    } else {
2411       struct isl_surf *surf = &res->surf;
2412       const struct isl_format_layout *fmtl =
2413          isl_format_get_layout(surf->format);
2414       const unsigned cpp = fmtl->bpb / 8;
2415       unsigned x0_el, y0_el;
2416 
2417       assert(box->x % fmtl->bw == 0);
2418       assert(box->y % fmtl->bh == 0);
2419       get_image_offset_el(surf, xfer->level, box->z, &x0_el, &y0_el);
2420 
2421       x0_el += box->x / fmtl->bw;
2422       y0_el += box->y / fmtl->bh;
2423 
2424       xfer->stride = isl_surf_get_row_pitch_B(surf);
2425       xfer->layer_stride = isl_surf_get_array_pitch(surf);
2426 
2427       map->ptr = ptr + y0_el * xfer->stride + x0_el * cpp;
2428    }
2429 }
2430 
2431 static bool
can_promote_to_async(const struct iris_resource * res,const struct pipe_box * box,enum pipe_map_flags usage)2432 can_promote_to_async(const struct iris_resource *res,
2433                      const struct pipe_box *box,
2434                      enum pipe_map_flags usage)
2435 {
2436    /* If we're writing to a section of the buffer that hasn't even been
2437     * initialized with useful data, then we can safely promote this write
2438     * to be unsynchronized.  This helps the common pattern of appending data.
2439     */
2440    return res->base.b.target == PIPE_BUFFER && (usage & PIPE_MAP_WRITE) &&
2441           !(usage & TC_TRANSFER_MAP_NO_INFER_UNSYNCHRONIZED) &&
2442           !util_ranges_intersect(&res->valid_buffer_range, box->x,
2443                                  box->x + box->width);
2444 }
2445 
2446 static bool
prefer_cpu_access(const struct iris_resource * res,const struct pipe_box * box,enum pipe_map_flags usage,unsigned level,bool map_would_stall)2447 prefer_cpu_access(const struct iris_resource *res,
2448                   const struct pipe_box *box,
2449                   enum pipe_map_flags usage,
2450                   unsigned level,
2451                   bool map_would_stall)
2452 {
2453    const enum iris_mmap_mode mmap_mode = iris_bo_mmap_mode(res->bo);
2454 
2455    /* We must be able to map it. */
2456    if (mmap_mode == IRIS_MMAP_NONE)
2457       return false;
2458 
2459    const bool write = usage & PIPE_MAP_WRITE;
2460    const bool read = usage & PIPE_MAP_READ;
2461    const bool preserve =
2462       res->base.b.target == PIPE_BUFFER && !(usage & PIPE_MAP_DISCARD_RANGE);
2463 
2464    /* We want to avoid uncached reads because they are slow. */
2465    if (read && mmap_mode != IRIS_MMAP_WB)
2466       return false;
2467 
2468    /* We want to avoid stalling.  We can't avoid stalling for reads, though,
2469     * because the destination of a GPU staging copy would be busy and stall
2470     * in the exact same manner.  So don't consider it for those.
2471     *
2472     * For buffer maps which aren't invalidating the destination, the GPU
2473     * staging copy path would have to read the existing buffer contents in
2474     * order to preserve them, effectively making it a read.  But a direct
2475     * mapping would be able to just write the necessary parts without the
2476     * overhead of the copy.  It may stall, but we would anyway.
2477     */
2478    if (map_would_stall && !read && !preserve)
2479       return false;
2480 
2481    /* Use the GPU for writes if it would compress the data. */
2482    if (write && isl_aux_usage_has_compression(res->aux.usage))
2483       return false;
2484 
2485    /* Writes & Cached CPU reads are fine as long as the primary is valid. */
2486    return !iris_has_invalid_primary(res, level, 1, box->z, box->depth);
2487 }
2488 
2489 static void *
iris_transfer_map(struct pipe_context * ctx,struct pipe_resource * resource,unsigned level,enum pipe_map_flags usage,const struct pipe_box * box,struct pipe_transfer ** ptransfer)2490 iris_transfer_map(struct pipe_context *ctx,
2491                   struct pipe_resource *resource,
2492                   unsigned level,
2493                   enum pipe_map_flags usage,
2494                   const struct pipe_box *box,
2495                   struct pipe_transfer **ptransfer)
2496 {
2497    struct iris_context *ice = (struct iris_context *)ctx;
2498    struct iris_resource *res = (struct iris_resource *)resource;
2499    struct isl_surf *surf = &res->surf;
2500 
2501    /* From GL_AMD_pinned_memory issues:
2502     *
2503     *     4) Is glMapBuffer on a shared buffer guaranteed to return the
2504     *        same system address which was specified at creation time?
2505     *
2506     *        RESOLVED: NO. The GL implementation might return a different
2507     *        virtual mapping of that memory, although the same physical
2508     *        page will be used.
2509     *
2510     * So don't ever use staging buffers.
2511     */
2512    if (res->base.is_user_ptr)
2513       usage |= PIPE_MAP_PERSISTENT;
2514 
2515    /* Promote discarding a range to discarding the entire buffer where
2516     * possible.  This may allow us to replace the backing storage entirely
2517     * and let us do an unsynchronized map when we otherwise wouldn't.
2518     */
2519    if (resource->target == PIPE_BUFFER &&
2520        (usage & PIPE_MAP_DISCARD_RANGE) &&
2521        box->x == 0 && box->width == resource->width0) {
2522       usage |= PIPE_MAP_DISCARD_WHOLE_RESOURCE;
2523    }
2524 
2525    if (usage & PIPE_MAP_DISCARD_WHOLE_RESOURCE) {
2526       /* Replace the backing storage with a fresh buffer for non-async maps */
2527       if (!(usage & (PIPE_MAP_UNSYNCHRONIZED | TC_TRANSFER_MAP_NO_INVALIDATE))
2528           && iris_invalidate_buffer(ice, res))
2529          usage |= PIPE_MAP_UNSYNCHRONIZED;
2530 
2531       /* If we can discard the whole resource, we can discard the range. */
2532       usage |= PIPE_MAP_DISCARD_RANGE;
2533    }
2534 
2535    if (!(usage & PIPE_MAP_UNSYNCHRONIZED) &&
2536        can_promote_to_async(res, box, usage)) {
2537       usage |= PIPE_MAP_UNSYNCHRONIZED;
2538    }
2539 
2540    /* We are dealing with external memory object PIPE_BUFFER, disable
2541     * async mapping because of sync issues.
2542     */
2543    if (!res->mod_info &&
2544        res->external_format != PIPE_FORMAT_NONE &&
2545        resource->target == PIPE_BUFFER) {
2546       usage &= ~PIPE_MAP_UNSYNCHRONIZED;
2547    }
2548 
2549    /* Avoid using GPU copies for persistent/coherent buffers, as the idea
2550     * there is to access them simultaneously on the CPU & GPU.  This also
2551     * avoids trying to use GPU copies for our u_upload_mgr buffers which
2552     * contain state we're constructing for a GPU draw call, which would
2553     * kill us with infinite stack recursion.
2554     */
2555    if (usage & (PIPE_MAP_PERSISTENT | PIPE_MAP_COHERENT))
2556       usage |= PIPE_MAP_DIRECTLY;
2557 
2558    /* We cannot provide a direct mapping of tiled resources, and we
2559     * may not be able to mmap imported BOs since they may come from
2560     * other devices that I915_GEM_MMAP cannot work with.
2561     */
2562    if ((usage & PIPE_MAP_DIRECTLY) &&
2563        (surf->tiling != ISL_TILING_LINEAR || iris_bo_is_imported(res->bo)))
2564       return NULL;
2565 
2566    bool map_would_stall = false;
2567 
2568    if (!(usage & PIPE_MAP_UNSYNCHRONIZED)) {
2569       map_would_stall =
2570          resource_is_busy(ice, res) ||
2571          iris_has_invalid_primary(res, level, 1, box->z, box->depth);
2572 
2573       if (map_would_stall && (usage & PIPE_MAP_DONTBLOCK) &&
2574                              (usage & PIPE_MAP_DIRECTLY))
2575          return NULL;
2576    }
2577 
2578    struct iris_transfer *map;
2579 
2580    if (usage & PIPE_MAP_THREAD_SAFE)
2581       map = CALLOC_STRUCT(iris_transfer);
2582    else if (usage & TC_TRANSFER_MAP_THREADED_UNSYNC)
2583       map = slab_zalloc(&ice->transfer_pool_unsync);
2584    else
2585       map = slab_zalloc(&ice->transfer_pool);
2586 
2587    if (!map)
2588       return NULL;
2589 
2590    struct pipe_transfer *xfer = &map->base.b;
2591 
2592    map->dbg = &ice->dbg;
2593 
2594    pipe_resource_reference(&xfer->resource, resource);
2595    xfer->level = level;
2596    xfer->usage = usage;
2597    xfer->box = *box;
2598    *ptransfer = xfer;
2599 
2600    if (usage & PIPE_MAP_WRITE)
2601       util_range_add(&res->base.b, &res->valid_buffer_range, box->x, box->x + box->width);
2602 
2603    if (prefer_cpu_access(res, box, usage, level, map_would_stall))
2604       usage |= PIPE_MAP_DIRECTLY;
2605 
2606    /* TODO: Teach iris_map_tiled_memcpy about Tile64... */
2607    if (isl_tiling_is_64(res->surf.tiling))
2608       usage &= ~PIPE_MAP_DIRECTLY;
2609 
2610    if (!(usage & PIPE_MAP_DIRECTLY)) {
2611       /* If we need a synchronous mapping and the resource is busy, or needs
2612        * resolving, we copy to/from a linear temporary buffer using the GPU.
2613        */
2614       map->batch = &ice->batches[IRIS_BATCH_RENDER];
2615       map->blorp = &ice->blorp;
2616       iris_map_copy_region(map);
2617    }
2618 
2619    /* If we've requested a direct mapping, or iris_map_copy_region failed
2620     * to create a staging resource, then map it directly on the CPU.
2621     */
2622    if (!map->ptr) {
2623       if (resource->target != PIPE_BUFFER) {
2624          iris_resource_access_raw(ice, res, level, box->z, box->depth,
2625                                   usage & PIPE_MAP_WRITE);
2626       }
2627 
2628       if (!(usage & PIPE_MAP_UNSYNCHRONIZED)) {
2629          iris_foreach_batch(ice, batch) {
2630             if (iris_batch_references(batch, res->bo))
2631                iris_batch_flush(batch);
2632          }
2633       }
2634 
2635       if (surf->tiling == ISL_TILING_W) {
2636          /* TODO: Teach iris_map_tiled_memcpy about W-tiling... */
2637          iris_map_s8(map);
2638       } else if (surf->tiling != ISL_TILING_LINEAR) {
2639          iris_map_tiled_memcpy(map);
2640       } else {
2641          iris_map_direct(map);
2642       }
2643    }
2644 
2645    return map->ptr;
2646 }
2647 
2648 static void
iris_transfer_flush_region(struct pipe_context * ctx,struct pipe_transfer * xfer,const struct pipe_box * box)2649 iris_transfer_flush_region(struct pipe_context *ctx,
2650                            struct pipe_transfer *xfer,
2651                            const struct pipe_box *box)
2652 {
2653    struct iris_context *ice = (struct iris_context *)ctx;
2654    struct iris_resource *res = (struct iris_resource *) xfer->resource;
2655    struct iris_transfer *map = (void *) xfer;
2656 
2657    if (map->staging)
2658       iris_flush_staging_region(xfer, box);
2659 
2660    if (res->base.b.target == PIPE_BUFFER) {
2661       util_range_add(&res->base.b, &res->valid_buffer_range, box->x, box->x + box->width);
2662    }
2663 
2664    /* Make sure we flag constants dirty even if there's no need to emit
2665     * any PIPE_CONTROLs to a batch.
2666     */
2667    iris_dirty_for_history(ice, res);
2668 }
2669 
2670 static void
iris_transfer_unmap(struct pipe_context * ctx,struct pipe_transfer * xfer)2671 iris_transfer_unmap(struct pipe_context *ctx, struct pipe_transfer *xfer)
2672 {
2673    struct iris_context *ice = (struct iris_context *)ctx;
2674    struct iris_transfer *map = (void *) xfer;
2675 
2676    if (!(xfer->usage & (PIPE_MAP_FLUSH_EXPLICIT |
2677                         PIPE_MAP_COHERENT))) {
2678       struct pipe_box flush_box = {
2679          .x = 0, .y = 0, .z = 0,
2680          .width  = xfer->box.width,
2681          .height = xfer->box.height,
2682          .depth  = xfer->box.depth,
2683       };
2684       iris_transfer_flush_region(ctx, xfer, &flush_box);
2685    }
2686 
2687    if (map->unmap)
2688       map->unmap(map);
2689 
2690    pipe_resource_reference(&xfer->resource, NULL);
2691 
2692    if (xfer->usage & PIPE_MAP_THREAD_SAFE) {
2693       free(map);
2694    } else {
2695       /* transfer_unmap is called from the driver thread, so we have to use
2696        * transfer_pool, not transfer_pool_unsync.  Freeing an object into a
2697        * different pool is allowed, however.
2698        */
2699       slab_free(&ice->transfer_pool, map);
2700    }
2701 }
2702 
2703 /**
2704  * The pipe->texture_subdata() driver hook.
2705  *
2706  * Mesa's state tracker takes this path whenever possible, even with
2707  * PIPE_CAP_TEXTURE_TRANSFER_MODES set.
2708  */
2709 static void
iris_texture_subdata(struct pipe_context * ctx,struct pipe_resource * resource,unsigned level,unsigned usage,const struct pipe_box * box,const void * data,unsigned stride,uintptr_t layer_stride)2710 iris_texture_subdata(struct pipe_context *ctx,
2711                      struct pipe_resource *resource,
2712                      unsigned level,
2713                      unsigned usage,
2714                      const struct pipe_box *box,
2715                      const void *data,
2716                      unsigned stride,
2717                      uintptr_t layer_stride)
2718 {
2719    struct iris_context *ice = (struct iris_context *)ctx;
2720    struct iris_resource *res = (struct iris_resource *)resource;
2721    const struct isl_surf *surf = &res->surf;
2722 
2723    assert(resource->target != PIPE_BUFFER);
2724 
2725    /* Just use the transfer-based path for linear buffers - it will already
2726     * do a direct mapping, or a simple linear staging buffer.
2727     *
2728     * Linear staging buffers appear to be better than tiled ones, too, so
2729     * take that path if we need the GPU to perform color compression, or
2730     * stall-avoidance blits.
2731     *
2732     * TODO: Teach isl_memcpy_linear_to_tiled about Tile64...
2733     */
2734    if (surf->tiling == ISL_TILING_LINEAR ||
2735        isl_tiling_is_64(res->surf.tiling) ||
2736        isl_aux_usage_has_compression(res->aux.usage) ||
2737        resource_is_busy(ice, res) ||
2738        iris_bo_mmap_mode(res->bo) == IRIS_MMAP_NONE) {
2739       return u_default_texture_subdata(ctx, resource, level, usage, box,
2740                                        data, stride, layer_stride);
2741    }
2742 
2743    /* No state trackers pass any flags other than PIPE_MAP_WRITE */
2744 
2745    iris_resource_access_raw(ice, res, level, box->z, box->depth, true);
2746 
2747    iris_foreach_batch(ice, batch) {
2748       if (iris_batch_references(batch, res->bo))
2749          iris_batch_flush(batch);
2750    }
2751 
2752    uint8_t *dst = iris_bo_map(&ice->dbg, res->bo, MAP_WRITE | MAP_RAW);
2753 
2754    for (int s = 0; s < box->depth; s++) {
2755       const uint8_t *src = data + s * layer_stride;
2756 
2757       if (surf->tiling == ISL_TILING_W) {
2758          unsigned x0_el, y0_el;
2759          get_image_offset_el(surf, level, box->z + s, &x0_el, &y0_el);
2760 
2761          for (unsigned y = 0; y < box->height; y++) {
2762             for (unsigned x = 0; x < box->width; x++) {
2763                ptrdiff_t offset = s8_offset(surf->row_pitch_B,
2764                                             x0_el + box->x + x,
2765                                             y0_el + box->y + y);
2766                dst[offset] = src[y * stride + x];
2767             }
2768          }
2769       } else {
2770          unsigned x1, x2, y1, y2;
2771 
2772          tile_extents(surf, box, level, s, &x1, &x2, &y1, &y2);
2773 
2774          isl_memcpy_linear_to_tiled(x1, x2, y1, y2,
2775                                     (void *)dst, (void *)src,
2776                                     surf->row_pitch_B, stride,
2777                                     false, surf->tiling, ISL_MEMCPY);
2778       }
2779    }
2780 }
2781 
2782 /**
2783  * Mark state dirty that needs to be re-emitted when a resource is written.
2784  */
2785 void
iris_dirty_for_history(struct iris_context * ice,struct iris_resource * res)2786 iris_dirty_for_history(struct iris_context *ice,
2787                        struct iris_resource *res)
2788 {
2789    const uint64_t stages = res->bind_stages;
2790    uint64_t dirty = 0ull;
2791    uint64_t stage_dirty = 0ull;
2792 
2793    if (res->bind_history & PIPE_BIND_CONSTANT_BUFFER) {
2794       for (unsigned stage = 0; stage < MESA_SHADER_STAGES; stage++) {
2795          if (stages & (1u << stage)) {
2796             struct iris_shader_state *shs = &ice->state.shaders[stage];
2797             shs->dirty_cbufs |= ~0u;
2798          }
2799       }
2800       dirty |= IRIS_DIRTY_RENDER_MISC_BUFFER_FLUSHES |
2801                IRIS_DIRTY_COMPUTE_MISC_BUFFER_FLUSHES;
2802       stage_dirty |= (stages << IRIS_SHIFT_FOR_STAGE_DIRTY_CONSTANTS);
2803    }
2804 
2805    if (res->bind_history & (PIPE_BIND_SAMPLER_VIEW |
2806                             PIPE_BIND_SHADER_IMAGE)) {
2807       dirty |= IRIS_DIRTY_RENDER_RESOLVES_AND_FLUSHES |
2808                IRIS_DIRTY_COMPUTE_RESOLVES_AND_FLUSHES;
2809       stage_dirty |= (stages << IRIS_SHIFT_FOR_STAGE_DIRTY_BINDINGS);
2810    }
2811 
2812    if (res->bind_history & PIPE_BIND_SHADER_BUFFER) {
2813       dirty |= IRIS_DIRTY_RENDER_MISC_BUFFER_FLUSHES |
2814                IRIS_DIRTY_COMPUTE_MISC_BUFFER_FLUSHES;
2815       stage_dirty |= (stages << IRIS_SHIFT_FOR_STAGE_DIRTY_BINDINGS);
2816    }
2817 
2818    if (res->bind_history & PIPE_BIND_VERTEX_BUFFER)
2819       dirty |= IRIS_DIRTY_VERTEX_BUFFER_FLUSHES;
2820 
2821    if (ice->state.streamout_active && (res->bind_history & PIPE_BIND_STREAM_OUTPUT))
2822       dirty |= IRIS_DIRTY_SO_BUFFERS;
2823 
2824    ice->state.dirty |= dirty;
2825    ice->state.stage_dirty |= stage_dirty;
2826 }
2827 
2828 bool
iris_resource_set_clear_color(struct iris_context * ice,struct iris_resource * res,union isl_color_value color)2829 iris_resource_set_clear_color(struct iris_context *ice,
2830                               struct iris_resource *res,
2831                               union isl_color_value color)
2832 {
2833    if (res->aux.clear_color_unknown ||
2834        memcmp(&res->aux.clear_color, &color, sizeof(color)) != 0) {
2835       res->aux.clear_color = color;
2836       res->aux.clear_color_unknown = false;
2837       return true;
2838    }
2839 
2840    return false;
2841 }
2842 
2843 static enum pipe_format
iris_resource_get_internal_format(struct pipe_resource * p_res)2844 iris_resource_get_internal_format(struct pipe_resource *p_res)
2845 {
2846    struct iris_resource *res = (void *) p_res;
2847    return res->internal_format;
2848 }
2849 
2850 static const struct u_transfer_vtbl transfer_vtbl = {
2851    .resource_create       = iris_resource_create,
2852    .resource_destroy      = iris_resource_destroy,
2853    .transfer_map          = iris_transfer_map,
2854    .transfer_unmap        = iris_transfer_unmap,
2855    .transfer_flush_region = iris_transfer_flush_region,
2856    .get_internal_format   = iris_resource_get_internal_format,
2857    .set_stencil           = iris_resource_set_separate_stencil,
2858    .get_stencil           = iris_resource_get_separate_stencil,
2859 };
2860 
2861 void
iris_init_screen_resource_functions(struct pipe_screen * pscreen)2862 iris_init_screen_resource_functions(struct pipe_screen *pscreen)
2863 {
2864    pscreen->query_dmabuf_modifiers = iris_query_dmabuf_modifiers;
2865    pscreen->is_dmabuf_modifier_supported = iris_is_dmabuf_modifier_supported;
2866    pscreen->get_dmabuf_modifier_planes = iris_get_dmabuf_modifier_planes;
2867    pscreen->resource_create_with_modifiers =
2868       iris_resource_create_with_modifiers;
2869    pscreen->resource_create = u_transfer_helper_resource_create;
2870    pscreen->resource_from_user_memory = iris_resource_from_user_memory;
2871    pscreen->resource_from_handle = iris_resource_from_handle;
2872    pscreen->resource_from_memobj = iris_resource_from_memobj_wrapper;
2873    pscreen->resource_get_handle = iris_resource_get_handle;
2874    pscreen->resource_get_param = iris_resource_get_param;
2875    pscreen->resource_destroy = u_transfer_helper_resource_destroy;
2876    pscreen->memobj_create_from_handle = iris_memobj_create_from_handle;
2877    pscreen->memobj_destroy = iris_memobj_destroy;
2878    pscreen->transfer_helper =
2879       u_transfer_helper_create(&transfer_vtbl,
2880                                U_TRANSFER_HELPER_SEPARATE_Z32S8 |
2881                                U_TRANSFER_HELPER_SEPARATE_STENCIL |
2882                                U_TRANSFER_HELPER_MSAA_MAP);
2883 }
2884 
2885 void
iris_init_resource_functions(struct pipe_context * ctx)2886 iris_init_resource_functions(struct pipe_context *ctx)
2887 {
2888    ctx->flush_resource = iris_flush_resource;
2889    ctx->invalidate_resource = iris_invalidate_resource;
2890    ctx->buffer_map = u_transfer_helper_transfer_map;
2891    ctx->texture_map = u_transfer_helper_transfer_map;
2892    ctx->transfer_flush_region = u_transfer_helper_transfer_flush_region;
2893    ctx->buffer_unmap = u_transfer_helper_transfer_unmap;
2894    ctx->texture_unmap = u_transfer_helper_transfer_unmap;
2895    ctx->buffer_subdata = u_default_buffer_subdata;
2896    ctx->clear_buffer = u_default_clear_buffer;
2897    ctx->texture_subdata = iris_texture_subdata;
2898 }
2899