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