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 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 */
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