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  * on the rights to use, copy, modify, merge, publish, distribute, sub
8  * license, and/or sell copies of the Software, and to permit persons to whom
9  * the Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18  * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21  * USE OR OTHER DEALINGS IN THE SOFTWARE.
22  */
23 #ifndef CROCUS_RESOURCE_H
24 #define CROCUS_RESOURCE_H
25 
26 #include "pipe/p_state.h"
27 #include "util/u_inlines.h"
28 #include "util/u_range.h"
29 #include "util/u_threaded_context.h"
30 #include "intel/isl/isl.h"
31 #include "intel/dev/intel_device_info.h"
32 #include "crocus_bufmgr.h"
33 
34 struct crocus_batch;
35 struct crocus_context;
36 
37 #define CROCUS_MAX_MIPLEVELS 15
38 
39 struct crocus_format_info {
40    enum isl_format fmt;
41    enum pipe_swizzle swizzles[4];
42 };
43 
44 static inline enum isl_channel_select
pipe_to_isl_swizzle(const enum pipe_swizzle pswz,bool green_to_blue)45 pipe_to_isl_swizzle(const enum pipe_swizzle pswz, bool green_to_blue)
46 {
47    unsigned swz = (pswz + 4) & 7;
48 
49    return (green_to_blue && swz == ISL_CHANNEL_SELECT_GREEN) ? ISL_CHANNEL_SELECT_BLUE : swz;
50 }
51 
52 static inline struct isl_swizzle
pipe_to_isl_swizzles(const enum pipe_swizzle pswz[4])53 pipe_to_isl_swizzles(const enum pipe_swizzle pswz[4])
54 {
55    struct isl_swizzle swz;
56    swz.r = pipe_to_isl_swizzle(pswz[0], false);
57    swz.g = pipe_to_isl_swizzle(pswz[1], false);
58    swz.b = pipe_to_isl_swizzle(pswz[2], false);
59    swz.a = pipe_to_isl_swizzle(pswz[3], false);
60    return swz;
61 }
62 
63 static inline void
crocus_combine_swizzle(enum pipe_swizzle outswz[4],const enum pipe_swizzle fswz[4],const enum pipe_swizzle vswz[4])64 crocus_combine_swizzle(enum pipe_swizzle outswz[4],
65                        const enum pipe_swizzle fswz[4],
66                        const enum pipe_swizzle vswz[4])
67 {
68    for (unsigned i = 0; i < 4; i++) {
69       switch (vswz[i]) {
70       case PIPE_SWIZZLE_X: outswz[i] = fswz[0]; break;
71       case PIPE_SWIZZLE_Y: outswz[i] = fswz[1]; break;
72       case PIPE_SWIZZLE_Z: outswz[i] = fswz[2]; break;
73       case PIPE_SWIZZLE_W: outswz[i] = fswz[3]; break;
74       case PIPE_SWIZZLE_1: outswz[i] = PIPE_SWIZZLE_1; break;
75       case PIPE_SWIZZLE_0: outswz[i] = PIPE_SWIZZLE_0; break;
76       default: unreachable("invalid swizzle");
77       }
78    }
79 }
80 
81 /**
82  * Resources represent a GPU buffer object or image (mipmap tree).
83  *
84  * They contain the storage (BO) and layout information (ISL surface).
85  */
86 struct crocus_resource {
87    struct threaded_resource base;
88    enum pipe_format internal_format;
89 
90    /**
91     * The ISL surface layout information for this resource.
92     *
93     * This is not filled out for PIPE_BUFFER resources, but is guaranteed
94     * to be zeroed.  Note that this also guarantees that res->surf.tiling
95     * will be ISL_TILING_LINEAR, so it's safe to check that.
96     */
97    struct isl_surf surf;
98 
99    /** Backing storage for the resource */
100    struct crocus_bo *bo;
101 
102    /** offset at which data starts in the BO */
103    uint64_t offset;
104 
105    /**
106     * A bitfield of PIPE_BIND_* indicating how this resource was bound
107     * in the past.  Only meaningful for PIPE_BUFFER; used for flushing.
108     */
109    unsigned bind_history;
110 
111    /**
112     * A bitfield of MESA_SHADER_* stages indicating where this resource
113     * was bound.
114     */
115    unsigned bind_stages;
116 
117    /**
118     * For PIPE_BUFFER resources, a range which may contain valid data.
119     *
120     * This is a conservative estimate of what part of the buffer contains
121     * valid data that we have to preserve.  The rest of the buffer is
122     * considered invalid, and we can promote writes to that region to
123     * be unsynchronized writes, avoiding blit copies.
124     */
125    struct util_range valid_buffer_range;
126 
127    /**
128     * Auxiliary buffer information (CCS, MCS, or HiZ).
129     */
130    struct {
131       /** The surface layout for the auxiliary buffer. */
132       struct isl_surf surf;
133 
134       /** The buffer object containing the auxiliary data. */
135       struct crocus_bo *bo;
136 
137       /** Offset into 'bo' where the auxiliary surface starts. */
138       uint32_t offset;
139 
140       /**
141        * Fast clear color for this surface.  For depth surfaces, the clear
142        * value is stored as a float32 in the red component.
143        */
144       union isl_color_value clear_color;
145 
146       /**
147        * \brief The type of auxiliary compression used by this resource.
148        *
149        * This describes the type of auxiliary compression that is intended to
150        * be used by this resource.  An aux usage of ISL_AUX_USAGE_NONE means
151        * that auxiliary compression is permanently disabled.  An aux usage
152        * other than ISL_AUX_USAGE_NONE does not imply that auxiliary
153        * compression will always be enabled for this surface.
154        */
155       enum isl_aux_usage usage;
156 
157       /**
158        * \brief Maps miptree slices to their current aux state.
159        *
160        * This two-dimensional array is indexed as [level][layer] and stores an
161        * aux state for each slice.
162        */
163       enum isl_aux_state **state;
164 
165       /**
166        * If (1 << level) is set, HiZ is enabled for that miplevel.
167        */
168       uint16_t has_hiz;
169    } aux;
170 
171    /**
172     * \brief Shadow miptree for sampling when the main isn't supported by HW.
173     *
174     * To workaround various sampler bugs and limitations, we blit the main
175     * texture into a new texture that can be sampled.
176     *
177     * This miptree may be used for:
178     * - Stencil texturing (pre-BDW) as required by GL_ARB_stencil_texturing.
179     */
180    struct crocus_resource *shadow;
181    bool shadow_needs_update;
182 
183    /**
184     * For external surfaces, this is format that was used to create or import
185     * the surface. For internal surfaces, this will always be
186     * PIPE_FORMAT_NONE.
187     */
188    enum pipe_format external_format;
189 
190    /**
191     * For external surfaces, this is DRM format modifier that was used to
192     * create or import the surface.  For internal surfaces, this will always
193     * be DRM_FORMAT_MOD_INVALID.
194     */
195    const struct isl_drm_modifier_info *mod_info;
196 
197    /**
198     * The screen the resource was originally created with, stored for refcounting.
199     */
200    struct pipe_screen *orig_screen;
201 };
202 
203 /**
204  * A simple <resource, offset> tuple for storing a reference to a
205  * piece of state stored in a GPU buffer object.
206  */
207 struct crocus_state_ref {
208    struct pipe_resource *res;
209    uint32_t offset;
210 };
211 
212 /**
213  * Gallium CSO for sampler views (texture views).
214  *
215  * In addition to the normal pipe_resource, this adds an ISL view
216  * which may reinterpret the format or restrict levels/layers.
217  *
218  * These can also be linear texture buffers.
219  */
220 struct crocus_sampler_view {
221    struct pipe_sampler_view base;
222    struct isl_view view;
223    struct isl_view gather_view;
224 
225    enum pipe_swizzle swizzle[4];
226    union isl_color_value clear_color;
227 
228    /* A short-cut (not a reference) to the actual resource being viewed.
229     * Multi-planar (or depth+stencil) images may have multiple resources
230     * chained together; this skips having to traverse base->texture->*.
231     */
232    struct crocus_resource *res;
233 };
234 
235 /**
236  * Image view representation.
237  */
238 struct crocus_image_view {
239    struct pipe_image_view base;
240    struct isl_view view;
241 };
242 
243 /**
244  * Gallium CSO for surfaces (framebuffer attachments).
245  *
246  * A view of a surface that can be bound to a color render target or
247  * depth/stencil attachment.
248  */
249 struct crocus_surface {
250    struct pipe_surface base;
251    struct isl_view view;
252    struct isl_view read_view;
253    struct isl_surf surf;
254    union isl_color_value clear_color;
255 
256    struct pipe_resource *align_res;
257 };
258 
259 /**
260  * Transfer object - information about a buffer mapping.
261  */
262 struct crocus_transfer {
263    struct threaded_transfer base;
264    struct pipe_debug_callback *dbg;
265    void *buffer;
266    void *ptr;
267 
268    /** A linear staging resource for GPU-based copy_region transfers. */
269    struct pipe_resource *staging;
270    struct blorp_context *blorp;
271    struct crocus_batch *batch;
272 
273    bool dest_had_defined_contents;
274    bool has_swizzling;
275 
276    void (*unmap)(struct crocus_transfer *);
277 };
278 
279 /**
280  * Memory Object
281  */
282 struct crocus_memory_object {
283    struct pipe_memory_object b;
284    struct crocus_bo *bo;
285    uint64_t format;
286    unsigned stride;
287 };
288 
289 /**
290  * Unwrap a pipe_resource to get the underlying crocus_bo (for convenience).
291  */
292 static inline struct crocus_bo *
crocus_resource_bo(struct pipe_resource * p_res)293 crocus_resource_bo(struct pipe_resource *p_res)
294 {
295    struct crocus_resource *res = (void *) p_res;
296    return res->bo;
297 }
298 
299 static inline uint32_t
crocus_mocs(const struct crocus_bo * bo,const struct isl_device * dev)300 crocus_mocs(const struct crocus_bo *bo,
301             const struct isl_device *dev)
302 {
303    return isl_mocs(dev, 0, bo && crocus_bo_is_external(bo));
304 }
305 
306 struct crocus_format_info crocus_format_for_usage(const struct intel_device_info *,
307                                                   enum pipe_format pf,
308                                                   isl_surf_usage_flags_t usage);
309 
310 static inline struct pipe_resource *
_crocus_resource_get_separate_stencil(struct pipe_resource * p_res)311 _crocus_resource_get_separate_stencil(struct pipe_resource *p_res)
312 {
313    /* For packed depth-stencil, we treat depth as the primary resource
314     * and store S8 as the "second plane" resource.
315     */
316    if (p_res->next && p_res->next->format == PIPE_FORMAT_S8_UINT)
317       return p_res->next;
318 
319    return NULL;
320 
321 }
322 static inline void
crocus_get_depth_stencil_resources(const struct intel_device_info * devinfo,struct pipe_resource * res,struct crocus_resource ** out_z,struct crocus_resource ** out_s)323 crocus_get_depth_stencil_resources(const struct intel_device_info *devinfo,
324                                    struct pipe_resource *res,
325                                    struct crocus_resource **out_z,
326                                    struct crocus_resource **out_s)
327 {
328    /* gen4/5 only supports packed ds */
329    if (devinfo->ver < 6) {
330       *out_z = (void *)res;
331       *out_s = (void *)res;
332       return;
333    }
334 
335    if (res && res->format != PIPE_FORMAT_S8_UINT) {
336       *out_z = (void *) res;
337       *out_s = (void *) _crocus_resource_get_separate_stencil(res);
338    } else {
339       *out_z = NULL;
340       *out_s = (void *) res;
341    }
342 }
343 
344 
345 bool crocus_resource_set_clear_color(struct crocus_context *ice,
346                                      struct crocus_resource *res,
347                                      union isl_color_value color);
348 union isl_color_value
349 crocus_resource_get_clear_color(const struct crocus_resource *res);
350 
351 void
352 crocus_replace_buffer_storage(struct pipe_context *ctx,
353                               struct pipe_resource *p_dst,
354                               struct pipe_resource *p_src,
355                               unsigned num_rebinds,
356                               uint32_t rebind_mask,
357                               uint32_t delete_buffer_id);
358 
359 void crocus_init_screen_resource_functions(struct pipe_screen *pscreen);
360 
361 void crocus_dirty_for_history(struct crocus_context *ice,
362                               struct crocus_resource *res);
363 uint32_t crocus_flush_bits_for_history(struct crocus_resource *res);
364 
365 void crocus_flush_and_dirty_for_history(struct crocus_context *ice,
366                                         struct crocus_batch *batch,
367                                         struct crocus_resource *res,
368                                         uint32_t extra_flags,
369                                         const char *reason);
370 
371 unsigned crocus_get_num_logical_layers(const struct crocus_resource *res,
372                                        unsigned level);
373 
374 void crocus_resource_disable_aux(struct crocus_resource *res);
375 
376 #define INTEL_REMAINING_LAYERS UINT32_MAX
377 #define INTEL_REMAINING_LEVELS UINT32_MAX
378 
379 void
380 crocus_hiz_exec(struct crocus_context *ice,
381                 struct crocus_batch *batch,
382                 struct crocus_resource *res,
383                 unsigned int level, unsigned int start_layer,
384                 unsigned int num_layers, enum isl_aux_op op,
385                 bool update_clear_depth);
386 
387 /**
388  * Prepare a miptree for access
389  *
390  * This function should be called prior to any access to miptree in order to
391  * perform any needed resolves.
392  *
393  * \param[in]  start_level    The first mip level to be accessed
394  *
395  * \param[in]  num_levels     The number of miplevels to be accessed or
396  *                            INTEL_REMAINING_LEVELS to indicate every level
397  *                            above start_level will be accessed
398  *
399  * \param[in]  start_layer    The first array slice or 3D layer to be accessed
400  *
401  * \param[in]  num_layers     The number of array slices or 3D layers be
402  *                            accessed or INTEL_REMAINING_LAYERS to indicate
403  *                            every layer above start_layer will be accessed
404  *
405  * \param[in]  aux_supported  Whether or not the access will support the
406  *                            miptree's auxiliary compression format;  this
407  *                            must be false for uncompressed miptrees
408  *
409  * \param[in]  fast_clear_supported Whether or not the access will support
410  *                                  fast clears in the miptree's auxiliary
411  *                                  compression format
412  */
413 void
414 crocus_resource_prepare_access(struct crocus_context *ice,
415                                struct crocus_resource *res,
416                                uint32_t start_level, uint32_t num_levels,
417                                uint32_t start_layer, uint32_t num_layers,
418                                enum isl_aux_usage aux_usage,
419                                bool fast_clear_supported);
420 
421 /**
422  * Complete a write operation
423  *
424  * This function should be called after any operation writes to a miptree.
425  * This will update the miptree's compression state so that future resolves
426  * happen correctly.  Technically, this function can be called before the
427  * write occurs but the caller must ensure that they don't interlace
428  * crocus_resource_prepare_access and crocus_resource_finish_write calls to
429  * overlapping layer/level ranges.
430  *
431  * \param[in]  level             The mip level that was written
432  *
433  * \param[in]  start_layer       The first array slice or 3D layer written
434  *
435  * \param[in]  num_layers        The number of array slices or 3D layers
436  *                               written or INTEL_REMAINING_LAYERS to indicate
437  *                               every layer above start_layer was written
438  *
439  * \param[in]  written_with_aux  Whether or not the write was done with
440  *                               auxiliary compression enabled
441  */
442 void
443 crocus_resource_finish_write(struct crocus_context *ice,
444                              struct crocus_resource *res, uint32_t level,
445                              uint32_t start_layer, uint32_t num_layers,
446                              enum isl_aux_usage aux_usage);
447 
448 /** Get the auxiliary compression state of a miptree slice */
449 enum isl_aux_state
450 crocus_resource_get_aux_state(const struct crocus_resource *res,
451                               uint32_t level, uint32_t layer);
452 
453 /**
454  * Set the auxiliary compression state of a miptree slice range
455  *
456  * This function directly sets the auxiliary compression state of a slice
457  * range of a miptree.  It only modifies data structures and does not do any
458  * resolves.  This should only be called by code which directly performs
459  * compression operations such as fast clears and resolves.  Most code should
460  * use crocus_resource_prepare_access or crocus_resource_finish_write.
461  */
462 void
463 crocus_resource_set_aux_state(struct crocus_context *ice,
464                               struct crocus_resource *res, uint32_t level,
465                               uint32_t start_layer, uint32_t num_layers,
466                               enum isl_aux_state aux_state);
467 
468 /**
469  * Prepare a miptree for raw access
470  *
471  * This helper prepares the miptree for access that knows nothing about any
472  * sort of compression whatsoever.  This is useful when mapping the surface or
473  * using it with the blitter.
474  */
475 static inline void
crocus_resource_access_raw(struct crocus_context * ice,struct crocus_resource * res,uint32_t level,uint32_t layer,uint32_t num_layers,bool write)476 crocus_resource_access_raw(struct crocus_context *ice,
477                            struct crocus_resource *res,
478                            uint32_t level, uint32_t layer,
479                            uint32_t num_layers,
480                            bool write)
481 {
482    crocus_resource_prepare_access(ice, res, level, 1, layer, num_layers,
483                                   ISL_AUX_USAGE_NONE, false);
484    if (write) {
485       crocus_resource_finish_write(ice, res, level, layer, num_layers,
486                                    ISL_AUX_USAGE_NONE);
487    }
488 }
489 
490 void
491 crocus_resource_get_image_offset(struct crocus_resource *res,
492                                  uint32_t level, uint32_t z,
493                                  uint32_t *x, uint32_t *y);
494 static inline enum isl_aux_usage
crocus_resource_texture_aux_usage(const struct crocus_resource * res)495 crocus_resource_texture_aux_usage(const struct crocus_resource *res)
496 {
497    return res->aux.usage == ISL_AUX_USAGE_MCS ? ISL_AUX_USAGE_MCS : ISL_AUX_USAGE_NONE;
498 }
499 
500 void crocus_resource_prepare_texture(struct crocus_context *ice,
501                                      struct crocus_resource *res,
502                                      enum isl_format view_format,
503                                      uint32_t start_level, uint32_t num_levels,
504                                      uint32_t start_layer, uint32_t num_layers);
505 
506 static inline bool
crocus_resource_unfinished_aux_import(struct crocus_resource * res)507 crocus_resource_unfinished_aux_import(struct crocus_resource *res)
508 {
509    return res->base.b.next != NULL && res->mod_info &&
510       res->mod_info->aux_usage != ISL_AUX_USAGE_NONE;
511 }
512 
513 void crocus_resource_finish_aux_import(struct pipe_screen *pscreen,
514                                        struct crocus_resource *res);
515 
516 bool crocus_has_invalid_primary(const struct crocus_resource *res,
517                                 unsigned start_level, unsigned num_levels,
518                                 unsigned start_layer, unsigned num_layers);
519 
520 void crocus_resource_check_level_layer(const struct crocus_resource *res,
521                                        uint32_t level, uint32_t layer);
522 
523 bool crocus_resource_level_has_hiz(const struct crocus_resource *res,
524                                    uint32_t level);
525 bool crocus_has_color_unresolved(const struct crocus_resource *res,
526                                  unsigned start_level, unsigned num_levels,
527                                  unsigned start_layer, unsigned num_layers);
528 
529 enum isl_aux_usage crocus_resource_render_aux_usage(struct crocus_context *ice,
530                                                     struct crocus_resource *res,
531                                                     uint32_t level,
532                                                     enum isl_format render_fmt,
533                                                     bool draw_aux_disabled);
534 void crocus_resource_prepare_render(struct crocus_context *ice,
535                                     struct crocus_resource *res, uint32_t level,
536                                     uint32_t start_layer, uint32_t layer_count,
537                                     enum isl_aux_usage aux_usage);
538 void crocus_resource_finish_render(struct crocus_context *ice,
539                                    struct crocus_resource *res, uint32_t level,
540                                    uint32_t start_layer, uint32_t layer_count,
541                                    enum isl_aux_usage aux_usage);
542 #endif
543