2 * Mesa 3-D graphics library
4 * Copyright (C) 2012-2013 LunarG, Inc.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
25 * Chia-I Wu <olv@lunarg.com>
28 #include "ilo_layout.h"
29 #include "ilo_screen.h"
30 #include "ilo_resource.h"
33 * From the Ivy Bridge PRM, volume 1 part 1, page 105:
35 * "In addition to restrictions on maximum height, width, and depth,
36 * surfaces are also restricted to a maximum size in bytes. This
37 * maximum is 2 GB for all products and all surface types."
39 static const size_t ilo_max_resource_size
= 1u << 31;
42 resource_get_bo_name(const struct pipe_resource
*templ
)
44 static const char *target_names
[PIPE_MAX_TEXTURE_TYPES
] = {
45 [PIPE_BUFFER
] = "buf",
46 [PIPE_TEXTURE_1D
] = "tex-1d",
47 [PIPE_TEXTURE_2D
] = "tex-2d",
48 [PIPE_TEXTURE_3D
] = "tex-3d",
49 [PIPE_TEXTURE_CUBE
] = "tex-cube",
50 [PIPE_TEXTURE_RECT
] = "tex-rect",
51 [PIPE_TEXTURE_1D_ARRAY
] = "tex-1d-array",
52 [PIPE_TEXTURE_2D_ARRAY
] = "tex-2d-array",
53 [PIPE_TEXTURE_CUBE_ARRAY
] = "tex-cube-array",
55 const char *name
= target_names
[templ
->target
];
57 if (templ
->target
== PIPE_BUFFER
) {
58 switch (templ
->bind
) {
59 case PIPE_BIND_VERTEX_BUFFER
:
62 case PIPE_BIND_INDEX_BUFFER
:
65 case PIPE_BIND_CONSTANT_BUFFER
:
68 case PIPE_BIND_STREAM_OUTPUT
:
80 resource_get_cpu_init(const struct pipe_resource
*templ
)
82 return (templ
->bind
& (PIPE_BIND_DEPTH_STENCIL
|
83 PIPE_BIND_RENDER_TARGET
|
84 PIPE_BIND_STREAM_OUTPUT
)) ? false : true;
87 static enum gen_surface_tiling
88 winsys_to_surface_tiling(enum intel_tiling_mode tiling
)
91 case INTEL_TILING_NONE
:
92 return GEN6_TILING_NONE
;
98 assert(!"unknown tiling");
99 return GEN6_TILING_NONE
;
103 static inline enum intel_tiling_mode
104 surface_to_winsys_tiling(enum gen_surface_tiling tiling
)
107 case GEN6_TILING_NONE
:
108 return INTEL_TILING_NONE
;
110 return INTEL_TILING_X
;
112 return INTEL_TILING_Y
;
114 assert(!"unknown tiling");
115 return GEN6_TILING_NONE
;
120 tex_free_slices(struct ilo_texture
*tex
)
122 FREE(tex
->slices
[0]);
126 tex_alloc_slices(struct ilo_texture
*tex
)
128 const struct pipe_resource
*templ
= &tex
->base
;
129 struct ilo_texture_slice
*slices
;
132 /* sum the depths of all levels */
134 for (lv
= 0; lv
<= templ
->last_level
; lv
++)
135 depth
+= u_minify(templ
->depth0
, lv
);
138 * There are (depth * tex->base.array_size) slices in total. Either depth
139 * is one (non-3D) or templ->array_size is one (non-array), but it does
142 slices
= CALLOC(depth
* templ
->array_size
, sizeof(*slices
));
146 tex
->slices
[0] = slices
;
148 /* point to the respective positions in the buffer */
149 for (lv
= 1; lv
<= templ
->last_level
; lv
++) {
150 tex
->slices
[lv
] = tex
->slices
[lv
- 1] +
151 u_minify(templ
->depth0
, lv
- 1) * templ
->array_size
;
158 tex_import_handle(struct ilo_texture
*tex
,
159 const struct winsys_handle
*handle
)
161 struct ilo_screen
*is
= ilo_screen(tex
->base
.screen
);
162 const char *name
= resource_get_bo_name(&tex
->base
);
163 enum intel_tiling_mode tiling
;
166 tex
->bo
= intel_winsys_import_handle(is
->winsys
, name
, handle
,
167 tex
->layout
.bo_height
, &tiling
, &pitch
);
171 if (!ilo_layout_update_for_imported_bo(&tex
->layout
,
172 winsys_to_surface_tiling(tiling
), pitch
)) {
173 ilo_err("imported handle has incompatible tiling/pitch\n");
174 intel_bo_unref(tex
->bo
);
183 tex_create_bo(struct ilo_texture
*tex
)
185 struct ilo_screen
*is
= ilo_screen(tex
->base
.screen
);
186 const char *name
= resource_get_bo_name(&tex
->base
);
187 const bool cpu_init
= resource_get_cpu_init(&tex
->base
);
190 bo
= intel_winsys_alloc_bo(is
->winsys
, name
,
191 tex
->layout
.bo_stride
* tex
->layout
.bo_height
, cpu_init
);
193 /* set the tiling for transfer and export */
194 if (bo
&& (tex
->layout
.tiling
== GEN6_TILING_X
||
195 tex
->layout
.tiling
== GEN6_TILING_Y
)) {
196 const enum intel_tiling_mode tiling
=
197 surface_to_winsys_tiling(tex
->layout
.tiling
);
199 if (intel_bo_set_tiling(bo
, tiling
, tex
->layout
.bo_stride
)) {
207 return (tex
->bo
!= NULL
);
211 tex_create_separate_stencil(struct ilo_texture
*tex
)
213 struct pipe_resource templ
= tex
->base
;
214 struct pipe_resource
*s8
;
217 * Unless PIPE_BIND_DEPTH_STENCIL is set, the resource may have other
218 * tilings. But that should be fine since it will never be bound as the
219 * stencil buffer, and our transfer code can handle all tilings.
221 templ
.format
= PIPE_FORMAT_S8_UINT
;
223 s8
= tex
->base
.screen
->resource_create(tex
->base
.screen
, &templ
);
227 tex
->separate_s8
= ilo_texture(s8
);
229 assert(tex
->separate_s8
->layout
.format
== PIPE_FORMAT_S8_UINT
);
235 tex_create_hiz(struct ilo_texture
*tex
)
237 const struct pipe_resource
*templ
= &tex
->base
;
238 struct ilo_screen
*is
= ilo_screen(tex
->base
.screen
);
241 tex
->aux_bo
= intel_winsys_alloc_bo(is
->winsys
, "hiz texture",
242 tex
->layout
.aux_stride
* tex
->layout
.aux_height
, false);
246 for (lv
= 0; lv
<= templ
->last_level
; lv
++) {
247 if (tex
->layout
.aux_enables
& (1 << lv
)) {
248 const unsigned num_slices
= (templ
->target
== PIPE_TEXTURE_3D
) ?
249 u_minify(templ
->depth0
, lv
) : templ
->array_size
;
250 unsigned flags
= ILO_TEXTURE_HIZ
;
252 /* this will trigger a HiZ resolve */
254 flags
|= ILO_TEXTURE_CPU_WRITE
;
256 ilo_texture_set_slice_flags(tex
, lv
, 0, num_slices
, flags
, flags
);
264 tex_create_mcs(struct ilo_texture
*tex
)
266 struct ilo_screen
*is
= ilo_screen(tex
->base
.screen
);
268 assert(tex
->layout
.aux_enables
== (1 << (tex
->base
.last_level
+ 1)) - 1);
270 tex
->aux_bo
= intel_winsys_alloc_bo(is
->winsys
, "mcs texture",
271 tex
->layout
.aux_stride
* tex
->layout
.aux_height
, false);
279 tex_destroy(struct ilo_texture
*tex
)
281 if (tex
->separate_s8
)
282 tex_destroy(tex
->separate_s8
);
284 intel_bo_unref(tex
->aux_bo
);
285 intel_bo_unref(tex
->bo
);
287 tex_free_slices(tex
);
292 tex_alloc_bos(struct ilo_texture
*tex
,
293 const struct winsys_handle
*handle
)
295 struct ilo_screen
*is
= ilo_screen(tex
->base
.screen
);
298 if (!tex_import_handle(tex
, handle
))
301 if (!tex_create_bo(tex
))
305 /* allocate separate stencil resource */
306 if (tex
->layout
.separate_stencil
&& !tex_create_separate_stencil(tex
))
309 switch (tex
->layout
.aux
) {
310 case ILO_LAYOUT_AUX_HIZ
:
311 if (!tex_create_hiz(tex
)) {
312 /* Separate Stencil Buffer requires HiZ to be enabled */
313 if (ilo_dev_gen(&is
->dev
) == ILO_GEN(6) &&
314 tex
->layout
.separate_stencil
)
318 case ILO_LAYOUT_AUX_MCS
:
319 if (!tex_create_mcs(tex
))
330 tex_init_layout(struct ilo_texture
*tex
)
332 struct ilo_screen
*is
= ilo_screen(tex
->base
.screen
);
333 const struct pipe_resource
*templ
= &tex
->base
;
334 struct ilo_layout
*layout
= &tex
->layout
;
336 ilo_layout_init(layout
, &is
->dev
, templ
);
338 if (layout
->bo_height
> ilo_max_resource_size
/ layout
->bo_stride
)
341 if (templ
->flags
& PIPE_RESOURCE_FLAG_MAP_PERSISTENT
) {
342 /* require on-the-fly tiling/untiling or format conversion */
343 if (layout
->tiling
== GEN8_TILING_W
|| layout
->separate_stencil
||
344 layout
->format
!= templ
->format
)
348 if (!tex_alloc_slices(tex
))
354 static struct pipe_resource
*
355 tex_create(struct pipe_screen
*screen
,
356 const struct pipe_resource
*templ
,
357 const struct winsys_handle
*handle
)
359 struct ilo_texture
*tex
;
361 tex
= CALLOC_STRUCT(ilo_texture
);
366 tex
->base
.screen
= screen
;
367 pipe_reference_init(&tex
->base
.reference
, 1);
369 tex
->imported
= (handle
!= NULL
);
371 if (!tex_init_layout(tex
)) {
376 if (!tex_alloc_bos(tex
, handle
)) {
385 tex_get_handle(struct ilo_texture
*tex
, struct winsys_handle
*handle
)
387 struct ilo_screen
*is
= ilo_screen(tex
->base
.screen
);
388 enum intel_tiling_mode tiling
;
391 /* must match what tex_create_bo() sets */
392 if (tex
->layout
.tiling
== GEN8_TILING_W
)
393 tiling
= INTEL_TILING_NONE
;
395 tiling
= surface_to_winsys_tiling(tex
->layout
.tiling
);
397 err
= intel_winsys_export_handle(is
->winsys
, tex
->bo
, tiling
,
398 tex
->layout
.bo_stride
, tex
->layout
.bo_height
, handle
);
404 buf_create_bo(struct ilo_buffer
*buf
)
406 struct ilo_screen
*is
= ilo_screen(buf
->base
.screen
);
407 const char *name
= resource_get_bo_name(&buf
->base
);
408 const bool cpu_init
= resource_get_cpu_init(&buf
->base
);
410 buf
->bo
= intel_winsys_alloc_bo(is
->winsys
, name
, buf
->bo_size
, cpu_init
);
412 return (buf
->bo
!= NULL
);
416 buf_destroy(struct ilo_buffer
*buf
)
418 intel_bo_unref(buf
->bo
);
422 static struct pipe_resource
*
423 buf_create(struct pipe_screen
*screen
, const struct pipe_resource
*templ
)
425 const struct ilo_screen
*is
= ilo_screen(screen
);
426 struct ilo_buffer
*buf
;
428 buf
= CALLOC_STRUCT(ilo_buffer
);
433 buf
->base
.screen
= screen
;
434 pipe_reference_init(&buf
->base
.reference
, 1);
436 buf
->bo_size
= templ
->width0
;
439 * From the Sandy Bridge PRM, volume 1 part 1, page 118:
441 * "For buffers, which have no inherent "height," padding requirements
442 * are different. A buffer must be padded to the next multiple of 256
443 * array elements, with an additional 16 bytes added beyond that to
444 * account for the L1 cache line."
446 if (templ
->bind
& PIPE_BIND_SAMPLER_VIEW
)
447 buf
->bo_size
= align(buf
->bo_size
, 256) + 16;
449 if ((templ
->bind
& PIPE_BIND_VERTEX_BUFFER
) &&
450 ilo_dev_gen(&is
->dev
) < ILO_GEN(7.5)) {
452 * As noted in ilo_translate_format(), we treat some 3-component formats
453 * as 4-component formats to work around hardware limitations. Imagine
454 * the case where the vertex buffer holds a single
455 * PIPE_FORMAT_R16G16B16_FLOAT vertex, and buf->bo_size is 6. The
456 * hardware would fail to fetch it at boundary check because the vertex
457 * buffer is expected to hold a PIPE_FORMAT_R16G16B16A16_FLOAT vertex
458 * and that takes at least 8 bytes.
460 * For the workaround to work, we should add 2 to the bo size. But that
461 * would waste a page when the bo size is already page aligned. Let's
462 * round it to page size for now and revisit this when needed.
464 buf
->bo_size
= align(buf
->bo_size
, 4096);
467 if (buf
->bo_size
< templ
->width0
||
468 buf
->bo_size
> ilo_max_resource_size
||
469 !buf_create_bo(buf
)) {
478 ilo_can_create_resource(struct pipe_screen
*screen
,
479 const struct pipe_resource
*templ
)
481 struct ilo_layout layout
;
483 if (templ
->target
== PIPE_BUFFER
)
484 return (templ
->width0
<= ilo_max_resource_size
);
486 memset(&layout
, 0, sizeof(layout
));
487 ilo_layout_init(&layout
, &ilo_screen(screen
)->dev
, templ
);
489 return (layout
.bo_height
<= ilo_max_resource_size
/ layout
.bo_stride
);
492 static struct pipe_resource
*
493 ilo_resource_create(struct pipe_screen
*screen
,
494 const struct pipe_resource
*templ
)
496 if (templ
->target
== PIPE_BUFFER
)
497 return buf_create(screen
, templ
);
499 return tex_create(screen
, templ
, NULL
);
502 static struct pipe_resource
*
503 ilo_resource_from_handle(struct pipe_screen
*screen
,
504 const struct pipe_resource
*templ
,
505 struct winsys_handle
*handle
)
507 if (templ
->target
== PIPE_BUFFER
)
510 return tex_create(screen
, templ
, handle
);
514 ilo_resource_get_handle(struct pipe_screen
*screen
,
515 struct pipe_resource
*res
,
516 struct winsys_handle
*handle
)
518 if (res
->target
== PIPE_BUFFER
)
521 return tex_get_handle(ilo_texture(res
), handle
);
526 ilo_resource_destroy(struct pipe_screen
*screen
,
527 struct pipe_resource
*res
)
529 if (res
->target
== PIPE_BUFFER
)
530 buf_destroy(ilo_buffer(res
));
532 tex_destroy(ilo_texture(res
));
536 * Initialize resource-related functions.
539 ilo_init_resource_functions(struct ilo_screen
*is
)
541 is
->base
.can_create_resource
= ilo_can_create_resource
;
542 is
->base
.resource_create
= ilo_resource_create
;
543 is
->base
.resource_from_handle
= ilo_resource_from_handle
;
544 is
->base
.resource_get_handle
= ilo_resource_get_handle
;
545 is
->base
.resource_destroy
= ilo_resource_destroy
;
549 ilo_buffer_rename_bo(struct ilo_buffer
*buf
)
551 struct intel_bo
*old_bo
= buf
->bo
;
553 if (buf_create_bo(buf
)) {
554 intel_bo_unref(old_bo
);
564 ilo_texture_rename_bo(struct ilo_texture
*tex
)
566 struct intel_bo
*old_bo
= tex
->bo
;
568 /* an imported texture cannot be renamed */
572 if (tex_create_bo(tex
)) {
573 intel_bo_unref(old_bo
);