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
34struct crocus_batch;
35struct crocus_context;
36
37#define CROCUS_MAX_MIPLEVELS 15
38
39struct crocus_format_info {
40   enum isl_format fmt;
41   enum pipe_swizzle swizzles[4];
42};
43
44static inline enum isl_channel_select
45pipe_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
52static inline struct isl_swizzle
53pipe_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
63static inline void
64crocus_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 */
86struct 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 */
207struct 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 */
220struct 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 */
238struct 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 */
249struct 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 */
262struct crocus_transfer {
263   struct threaded_transfer base;
264   struct util_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 */
282struct 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 */
292static inline struct crocus_bo *
293crocus_resource_bo(struct pipe_resource *p_res)
294{
295   struct crocus_resource *res = (void *) p_res;
296   return res->bo;
297}
298
299static inline uint32_t
300crocus_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
306struct 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
310static inline struct pipe_resource *
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}
322static inline void
323crocus_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
345bool crocus_resource_set_clear_color(struct crocus_context *ice,
346                                     struct crocus_resource *res,
347                                     union isl_color_value color);
348union isl_color_value
349crocus_resource_get_clear_color(const struct crocus_resource *res);
350
351void
352crocus_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
359void crocus_init_screen_resource_functions(struct pipe_screen *pscreen);
360
361void crocus_dirty_for_history(struct crocus_context *ice,
362                              struct crocus_resource *res);
363uint32_t crocus_flush_bits_for_history(struct crocus_resource *res);
364
365void 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
371unsigned crocus_get_num_logical_layers(const struct crocus_resource *res,
372                                       unsigned level);
373
374void crocus_resource_disable_aux(struct crocus_resource *res);
375
376#define INTEL_REMAINING_LAYERS UINT32_MAX
377#define INTEL_REMAINING_LEVELS UINT32_MAX
378
379void
380crocus_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 */
413void
414crocus_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 */
442void
443crocus_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 */
449enum isl_aux_state
450crocus_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 */
462void
463crocus_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 */
475static inline void
476crocus_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
490void
491crocus_resource_get_image_offset(struct crocus_resource *res,
492                                 uint32_t level, uint32_t z,
493                                 uint32_t *x, uint32_t *y);
494static inline enum isl_aux_usage
495crocus_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
500void 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
506static inline bool
507crocus_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
513void crocus_resource_finish_aux_import(struct pipe_screen *pscreen,
514                                       struct crocus_resource *res);
515
516bool crocus_has_invalid_primary(const struct crocus_resource *res,
517                                unsigned start_level, unsigned num_levels,
518                                unsigned start_layer, unsigned num_layers);
519
520void crocus_resource_check_level_layer(const struct crocus_resource *res,
521                                       uint32_t level, uint32_t layer);
522
523bool crocus_resource_level_has_hiz(const struct crocus_resource *res,
524                                   uint32_t level);
525bool crocus_has_color_unresolved(const struct crocus_resource *res,
526                                 unsigned start_level, unsigned num_levels,
527                                 unsigned start_layer, unsigned num_layers);
528
529enum 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);
534void 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);
538void 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