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 "util/u_transfer.h"
31 #include "ilo_context.h"
32 #include "ilo_screen.h"
33 #include "ilo_resource.h"
35 static struct intel_bo
*
36 alloc_buf_bo(const struct ilo_resource
*res
)
38 struct ilo_screen
*is
= ilo_screen(res
->base
.screen
);
41 const unsigned size
= res
->bo_width
;
43 switch (res
->base
.bind
) {
44 case PIPE_BIND_VERTEX_BUFFER
:
45 name
= "vertex buffer";
47 case PIPE_BIND_INDEX_BUFFER
:
48 name
= "index buffer";
50 case PIPE_BIND_CONSTANT_BUFFER
:
51 name
= "constant buffer";
53 case PIPE_BIND_STREAM_OUTPUT
:
54 name
= "stream output";
57 name
= "unknown buffer";
61 /* this is what a buffer supposed to be like */
62 assert(res
->bo_width
* res
->bo_height
* res
->bo_cpp
== size
);
63 assert(res
->tiling
== INTEL_TILING_NONE
);
64 assert(res
->bo_stride
== 0);
67 bo
= is
->winsys
->import_handle(is
->winsys
, name
,
68 res
->bo_width
, res
->bo_height
, res
->bo_cpp
, res
->handle
);
70 /* since the bo is shared to us, make sure it meets the expectations */
72 assert(bo
->get_size(res
->bo
) == size
);
73 assert(bo
->get_tiling(res
->bo
) == res
->tiling
);
74 assert(bo
->get_pitch(res
->bo
) == res
->bo_stride
);
78 bo
= is
->winsys
->alloc_buffer(is
->winsys
, name
, size
, 0);
84 static struct intel_bo
*
85 alloc_tex_bo(const struct ilo_resource
*res
)
87 struct ilo_screen
*is
= ilo_screen(res
->base
.screen
);
91 switch (res
->base
.target
) {
101 case PIPE_TEXTURE_CUBE
:
102 name
= "cube texture";
104 case PIPE_TEXTURE_RECT
:
105 name
= "rectangle texture";
107 case PIPE_TEXTURE_1D_ARRAY
:
108 name
= "1D array texture";
110 case PIPE_TEXTURE_2D_ARRAY
:
111 name
= "2D array texture";
113 case PIPE_TEXTURE_CUBE_ARRAY
:
114 name
= "cube array texture";
117 name
="unknown texture";
122 bo
= is
->winsys
->import_handle(is
->winsys
, name
,
123 res
->bo_width
, res
->bo_height
, res
->bo_cpp
, res
->handle
);
126 const bool for_render
=
127 (res
->base
.bind
& (PIPE_BIND_DEPTH_STENCIL
|
128 PIPE_BIND_RENDER_TARGET
));
129 const unsigned long flags
=
130 (for_render
) ? INTEL_ALLOC_FOR_RENDER
: 0;
132 bo
= is
->winsys
->alloc(is
->winsys
, name
,
133 res
->bo_width
, res
->bo_height
, res
->bo_cpp
,
141 realloc_bo(struct ilo_resource
*res
)
143 struct intel_bo
*old_bo
= res
->bo
;
145 /* a shared bo cannot be reallocated */
146 if (old_bo
&& res
->handle
)
149 if (res
->base
.target
== PIPE_BUFFER
)
150 res
->bo
= alloc_buf_bo(res
);
152 res
->bo
= alloc_tex_bo(res
);
159 /* winsys may decide to use a different tiling */
160 res
->tiling
= res
->bo
->get_tiling(res
->bo
);
161 res
->bo_stride
= res
->bo
->get_pitch(res
->bo
);
164 old_bo
->unreference(old_bo
);
170 ilo_transfer_inline_write(struct pipe_context
*pipe
,
171 struct pipe_resource
*r
,
174 const struct pipe_box
*box
,
177 unsigned layer_stride
)
179 struct ilo_context
*ilo
= ilo_context(pipe
);
180 struct ilo_resource
*res
= ilo_resource(r
);
185 * Fall back to map(), memcpy(), and unmap(). We use this path for
186 * unsynchronized write, as the buffer is likely to be busy and pwrite()
189 if (unlikely(res
->base
.target
!= PIPE_BUFFER
) ||
190 (usage
& PIPE_TRANSFER_UNSYNCHRONIZED
)) {
191 u_default_transfer_inline_write(pipe
, r
,
192 level
, usage
, box
, data
, stride
, layer_stride
);
198 * XXX With hardware context support, the bo may be needed by GPU without
199 * being referenced by ilo->cp->bo. We have to flush unconditionally, and
203 ilo_cp_flush(ilo
->cp
);
205 will_be_busy
= ilo
->cp
->bo
->references(ilo
->cp
->bo
, res
->bo
);
207 /* see if we can avoid stalling */
208 if (will_be_busy
|| intel_bo_is_busy(res
->bo
)) {
209 bool will_stall
= true;
211 if (usage
& PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE
) {
212 /* old data not needed so discard the old bo to avoid stalling */
218 * We could allocate a temporary bo to hold the data and emit
219 * pipelined copy blit to move them to res->bo. But for now, do
224 /* flush to make bo busy (so that pwrite() stalls as it should be) */
225 if (will_stall
&& will_be_busy
)
226 ilo_cp_flush(ilo
->cp
);
229 /* they should specify just an offset and a size */
233 assert(box
->height
== 1);
234 assert(box
->depth
== 1);
238 res
->bo
->pwrite(res
->bo
, offset
, size
, data
);
242 ilo_transfer_unmap(struct pipe_context
*pipe
,
243 struct pipe_transfer
*transfer
)
245 struct ilo_resource
*res
= ilo_resource(transfer
->resource
);
247 res
->bo
->unmap(res
->bo
);
249 pipe_resource_reference(&transfer
->resource
, NULL
);
254 ilo_transfer_flush_region(struct pipe_context
*pipe
,
255 struct pipe_transfer
*transfer
,
256 const struct pipe_box
*box
)
261 map_resource(struct ilo_context
*ilo
, struct ilo_resource
*res
,
264 struct ilo_screen
*is
= ilo_screen(res
->base
.screen
);
268 /* simply map unsynchronized */
269 if (usage
& PIPE_TRANSFER_UNSYNCHRONIZED
) {
270 err
= res
->bo
->map_unsynchronized(res
->bo
);
275 * XXX With hardware context support, the bo may be needed by GPU without
276 * being referenced by ilo->cp->bo. We have to flush unconditionally, and
280 ilo_cp_flush(ilo
->cp
);
282 will_be_busy
= ilo
->cp
->bo
->references(ilo
->cp
->bo
, res
->bo
);
284 /* see if we can avoid stalling */
285 if (will_be_busy
|| intel_bo_is_busy(res
->bo
)) {
286 bool will_stall
= true;
288 if (usage
& PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE
) {
289 /* discard old bo and allocate a new one for mapping */
293 else if (usage
& PIPE_TRANSFER_MAP_DIRECTLY
) {
294 /* nothing we can do */
296 else if (usage
& PIPE_TRANSFER_FLUSH_EXPLICIT
) {
298 * We could allocate and return a system buffer here. When a region
299 * of the buffer is explicitly flushed, we pwrite() the region to a
300 * temporary bo and emit pipelined copy blit.
302 * For now, do nothing.
305 else if (usage
& PIPE_TRANSFER_DISCARD_RANGE
) {
307 * We could allocate a temporary bo for mapping, and emit pipelined
308 * copy blit upon unmapping.
310 * For now, do nothing.
315 if (usage
& PIPE_TRANSFER_DONTBLOCK
)
318 /* flush to make bo busy (so that map() stalls as it should be) */
320 ilo_cp_flush(ilo
->cp
);
324 /* prefer map() when there is the last-level cache */
325 if (res
->tiling
== INTEL_TILING_NONE
&&
326 (is
->dev
.has_llc
|| (usage
& PIPE_TRANSFER_READ
)))
327 err
= res
->bo
->map(res
->bo
, (usage
& PIPE_TRANSFER_WRITE
));
329 err
= res
->bo
->map_gtt(res
->bo
);
335 ilo_transfer_map(struct pipe_context
*pipe
,
336 struct pipe_resource
*r
,
339 const struct pipe_box
*box
,
340 struct pipe_transfer
**transfer
)
342 struct ilo_context
*ilo
= ilo_context(pipe
);
343 struct ilo_resource
*res
= ilo_resource(r
);
344 struct pipe_transfer
*xfer
;
348 xfer
= MALLOC_STRUCT(pipe_transfer
);
352 if (!map_resource(ilo
, res
, usage
)) {
358 xfer
->resource
= NULL
;
359 pipe_resource_reference(&xfer
->resource
, &res
->base
);
363 /* stride for a block row, not a texel row */
364 xfer
->stride
= res
->bo_stride
;
367 * we can walk through layers when the resource is a texture array or
368 * when this is the first level of a 3D texture being mapped
370 if (res
->base
.array_size
> 1 ||
371 (res
->base
.target
== PIPE_TEXTURE_3D
&& level
== 0)) {
372 const unsigned qpitch
=
373 res
->slice_offsets
[level
][1].y
- res
->slice_offsets
[level
][0].y
;
375 assert(qpitch
% res
->block_height
== 0);
376 xfer
->layer_stride
= (qpitch
/ res
->block_height
) * xfer
->stride
;
379 xfer
->layer_stride
= 0;
382 x
= res
->slice_offsets
[level
][box
->z
].x
;
383 y
= res
->slice_offsets
[level
][box
->z
].y
;
389 assert(x
% res
->block_width
== 0 && y
% res
->block_height
== 0);
390 x
/= res
->block_width
;
391 y
/= res
->block_height
;
393 ptr
= res
->bo
->get_virtual(res
->bo
);
394 ptr
+= y
* res
->bo_stride
+ x
* res
->bo_cpp
;
402 alloc_slice_offsets(struct ilo_resource
*res
)
406 /* sum the depths of all levels */
408 for (lv
= 0; lv
<= res
->base
.last_level
; lv
++)
409 depth
+= u_minify(res
->base
.depth0
, lv
);
412 * There are (depth * res->base.array_size) slices. Either depth is one
413 * (non-3D) or res->base.array_size is one (non-array), but it does not
416 res
->slice_offsets
[0] =
417 CALLOC(depth
* res
->base
.array_size
, sizeof(res
->slice_offsets
[0][0]));
418 if (!res
->slice_offsets
[0])
421 /* point to the respective positions in the buffer */
422 for (lv
= 1; lv
<= res
->base
.last_level
; lv
++) {
423 res
->slice_offsets
[lv
] = res
->slice_offsets
[lv
- 1] +
424 u_minify(res
->base
.depth0
, lv
- 1) * res
->base
.array_size
;
431 free_slice_offsets(struct ilo_resource
*res
)
435 FREE(res
->slice_offsets
[0]);
436 for (lv
= 0; lv
<= res
->base
.last_level
; lv
++)
437 res
->slice_offsets
[lv
] = NULL
;
440 struct layout_tex_info
{
442 int block_width
, block_height
;
443 int align_i
, align_j
;
448 } sizes
[PIPE_MAX_TEXTURE_LEVELS
];
452 * Prepare for texture layout.
455 layout_tex_init(const struct ilo_resource
*res
, struct layout_tex_info
*info
)
457 struct ilo_screen
*is
= ilo_screen(res
->base
.screen
);
458 const enum intel_tiling_mode tiling
= res
->tiling
;
459 const struct pipe_resource
*templ
= &res
->base
;
462 memset(info
, 0, sizeof(*info
));
464 info
->compressed
= util_format_is_compressed(templ
->format
);
465 info
->block_width
= util_format_get_blockwidth(templ
->format
);
466 info
->block_height
= util_format_get_blockheight(templ
->format
);
469 * From the Sandy Bridge PRM, volume 1 part 1, page 113:
471 * "surface format align_i align_j
472 * YUV 4:2:2 formats 4 *see below
475 * all other formats 4 *see below"
477 * "- align_j = 4 for any depth buffer
478 * - align_j = 2 for separate stencil buffer
479 * - align_j = 4 for any render target surface is multisampled (4x)
480 * - align_j = 4 for any render target surface with Surface Vertical
481 * Alignment = VALIGN_4
482 * - align_j = 2 for any render target surface with Surface Vertical
483 * Alignment = VALIGN_2
484 * - align_j = 2 for all other render target surface
485 * - align_j = 2 for any sampling engine surface with Surface Vertical
486 * Alignment = VALIGN_2
487 * - align_j = 4 for any sampling engine surface with Surface Vertical
488 * Alignment = VALIGN_4"
490 * From the Sandy Bridge PRM, volume 4 part 1, page 86:
492 * "This field (Surface Vertical Alignment) must be set to VALIGN_2 if
493 * the Surface Format is 96 bits per element (BPE)."
495 * They can be rephrased as
498 * compressed formats block width block height
499 * PIPE_FORMAT_S8_UINT 4 2
500 * other depth/stencil formats 4 4
501 * 4x multisampled 4 4
507 * From the Ivy Bridge PRM, volume 1 part 1, page 110:
509 * "surface defined by surface format align_i align_j
510 * 3DSTATE_DEPTH_BUFFER D16_UNORM 8 4
512 * 3DSTATE_STENCIL_BUFFER N/A 8 8
513 * SURFACE_STATE BC*, ETC*, EAC* 4 4
515 * all others (set by SURFACE_STATE)"
517 * From the Ivy Bridge PRM, volume 4 part 1, page 63:
519 * "- This field (Surface Vertical Aligment) is intended to be set to
520 * VALIGN_4 if the surface was rendered as a depth buffer, for a
521 * multisampled (4x) render target, or for a multisampled (8x)
522 * render target, since these surfaces support only alignment of 4.
523 * - Use of VALIGN_4 for other surfaces is supported, but uses more
525 * - This field must be set to VALIGN_4 for all tiled Y Render Target
527 * - Value of 1 is not supported for format YCRCB_NORMAL (0x182),
528 * YCRCB_SWAPUVY (0x183), YCRCB_SWAPUV (0x18f), YCRCB_SWAPY (0x190)
529 * - If Number of Multisamples is not MULTISAMPLECOUNT_1, this field
530 * must be set to VALIGN_4."
531 * - VALIGN_4 is not supported for surface format R32G32B32_FLOAT."
533 * "- This field (Surface Horizontal Aligment) is intended to be set to
534 * HALIGN_8 only if the surface was rendered as a depth buffer with
535 * Z16 format or a stencil buffer, since these surfaces support only
537 * - Use of HALIGN_8 for other surfaces is supported, but uses more
539 * - This field must be set to HALIGN_4 if the Surface Format is BC*.
540 * - This field must be set to HALIGN_8 if the Surface Format is
543 * They can be rephrased as
546 * compressed formats block width block height
547 * PIPE_FORMAT_Z16_UNORM 8 4
548 * PIPE_FORMAT_S8_UINT 8 8
549 * other depth/stencil formats 4 or 8 4
550 * 2x or 4x multisampled 4 or 8 4
551 * tiled Y 4 or 8 4 (if rt)
552 * PIPE_FORMAT_R32G32B32_FLOAT 4 or 8 2
553 * others 4 or 8 2 or 4
556 if (info
->compressed
) {
557 /* this happens to be the case */
558 info
->align_i
= info
->block_width
;
559 info
->align_j
= info
->block_height
;
561 else if (util_format_is_depth_or_stencil(templ
->format
)) {
562 if (is
->dev
.gen
>= ILO_GEN(7)) {
563 switch (templ
->format
) {
564 case PIPE_FORMAT_Z16_UNORM
:
568 case PIPE_FORMAT_S8_UINT
:
574 * From the Ivy Bridge PRM, volume 2 part 1, page 319:
576 * "The 3 LSBs of both offsets (Depth Coordinate Offset Y and
577 * Depth Coordinate Offset X) must be zero to ensure correct
580 * We will make use of them and setting align_i to 8 help us meet
583 info
->align_i
= (templ
->last_level
> 0) ? 8 : 4;
589 switch (templ
->format
) {
590 case PIPE_FORMAT_S8_UINT
:
602 const bool valign_4
= (templ
->nr_samples
> 1) ||
603 (is
->dev
.gen
>= ILO_GEN(7) &&
604 (templ
->bind
& PIPE_BIND_RENDER_TARGET
) &&
605 tiling
== INTEL_TILING_Y
);
608 assert(util_format_get_blocksizebits(templ
->format
) != 96);
611 info
->align_j
= (valign_4
) ? 4 : 2;
615 * the fact that align i and j are multiples of block width and height
616 * respectively is what makes the size of the bo a multiple of the block
617 * size, slices start at block boundaries, and many of the computations
620 assert(info
->align_i
% info
->block_width
== 0);
621 assert(info
->align_j
% info
->block_height
== 0);
623 /* make sure align() works */
624 assert(util_is_power_of_two(info
->align_i
) &&
625 util_is_power_of_two(info
->align_j
));
626 assert(util_is_power_of_two(info
->block_width
) &&
627 util_is_power_of_two(info
->block_height
));
629 last_level
= templ
->last_level
;
630 /* need at least 2 levels to compute qpitch below */
631 if (templ
->array_size
> 1 && last_level
== 0 &&
632 templ
->format
!= PIPE_FORMAT_S8_UINT
)
635 /* compute mip level sizes */
636 for (lv
= 0; lv
<= last_level
; lv
++) {
639 w
= u_minify(templ
->width0
, lv
);
640 h
= u_minify(templ
->height0
, lv
);
641 d
= u_minify(templ
->depth0
, lv
);
644 * From the Sandy Bridge PRM, volume 1 part 1, page 114:
646 * "The dimensions of the mip maps are first determined by applying
647 * the sizing algorithm presented in Non-Power-of-Two Mipmaps
648 * above. Then, if necessary, they are padded out to compression
651 w
= align(w
, info
->block_width
);
652 h
= align(h
, info
->block_height
);
655 * From the Sandy Bridge PRM, volume 1 part 1, page 111:
657 * "If the surface is multisampled (4x), these values must be
658 * adjusted as follows before proceeding:
660 * W_L = ceiling(W_L / 2) * 4
661 * H_L = ceiling(H_L / 2) * 4"
663 if (templ
->nr_samples
> 1) {
668 info
->sizes
[lv
].w
= w
;
669 info
->sizes
[lv
].h
= h
;
670 info
->sizes
[lv
].d
= d
;
673 if (templ
->array_size
> 1) {
674 const int h0
= align(info
->sizes
[0].h
, info
->align_j
);
676 if (templ
->format
== PIPE_FORMAT_S8_UINT
) {
680 const int h1
= align(info
->sizes
[1].h
, info
->align_j
);
683 * From the Sandy Bridge PRM, volume 1 part 1, page 115:
685 * "The following equation is used for surface formats other than
686 * compressed textures:
688 * QPitch = (h0 + h1 + 11j)"
690 * "The equation for compressed textures (BC* and FXT1 surface
693 * QPitch = (h0 + h1 + 11j) / 4"
695 * "[DevSNB] Errata: Sampler MSAA Qpitch will be 4 greater than
696 * the value calculated in the equation above, for every other
697 * odd Surface Height starting from 1 i.e. 1,5,9,13"
699 * To access the N-th slice, an offset of (Stride * QPitch * N) is
700 * added to the base address. The PRM divides QPitch by 4 for
701 * compressed formats because the block height for those formats are
702 * 4, and it wants QPitch to mean the number of memory rows, as
703 * opposed to texel rows, between slices. Since we use texel rows in
704 * res->slice_offsets, we do not need to divide QPitch by 4.
706 info
->qpitch
= h0
+ h1
+
707 ((is
->dev
.gen
>= ILO_GEN(7)) ? 12 : 11) * info
->align_j
;
709 if (is
->dev
.gen
== ILO_GEN(6) && templ
->nr_samples
> 1 &&
710 templ
->height0
% 4 == 1)
717 * Layout a 2D texture.
720 layout_tex_2d(struct ilo_resource
*res
, const struct layout_tex_info
*info
)
722 const struct pipe_resource
*templ
= &res
->base
;
723 unsigned int level_x
, level_y
;
731 for (lv
= 0; lv
<= templ
->last_level
; lv
++) {
732 const unsigned int level_w
= info
->sizes
[lv
].w
;
733 const unsigned int level_h
= info
->sizes
[lv
].h
;
736 for (slice
= 0; slice
< templ
->array_size
; slice
++) {
737 res
->slice_offsets
[lv
][slice
].x
= level_x
;
738 /* slices are qpitch apart in Y-direction */
739 res
->slice_offsets
[lv
][slice
].y
= level_y
+ info
->qpitch
* slice
;
742 /* extend the size of the monolithic bo to cover this mip level */
743 if (res
->bo_width
< level_x
+ level_w
)
744 res
->bo_width
= level_x
+ level_w
;
745 if (res
->bo_height
< level_y
+ level_h
)
746 res
->bo_height
= level_y
+ level_h
;
748 /* MIPLAYOUT_BELOW */
750 level_x
+= align(level_w
, info
->align_i
);
752 level_y
+= align(level_h
, info
->align_j
);
755 /* we did not take slices into consideration in the computation above */
756 res
->bo_height
+= info
->qpitch
* (templ
->array_size
- 1);
760 * Layout a 3D texture.
763 layout_tex_3d(struct ilo_resource
*res
, const struct layout_tex_info
*info
)
765 const struct pipe_resource
*templ
= &res
->base
;
766 unsigned int level_y
;
773 for (lv
= 0; lv
<= templ
->last_level
; lv
++) {
774 const unsigned int level_w
= info
->sizes
[lv
].w
;
775 const unsigned int level_h
= info
->sizes
[lv
].h
;
776 const unsigned int level_d
= info
->sizes
[lv
].d
;
777 const unsigned int slice_pitch
= align(level_w
, info
->align_i
);
778 const unsigned int slice_qpitch
= align(level_h
, info
->align_j
);
779 const unsigned int num_slices_per_row
= 1 << lv
;
782 for (slice
= 0; slice
< level_d
; slice
+= num_slices_per_row
) {
785 for (i
= 0; i
< num_slices_per_row
&& slice
+ i
< level_d
; i
++) {
786 res
->slice_offsets
[lv
][slice
+ i
].x
= slice_pitch
* i
;
787 res
->slice_offsets
[lv
][slice
+ i
].y
= level_y
;
790 /* move on to the next slice row */
791 level_y
+= slice_qpitch
;
794 /* rightmost slice */
795 slice
= MIN2(num_slices_per_row
, level_d
) - 1;
797 /* extend the size of the monolithic bo to cover this slice */
798 if (res
->bo_width
< slice_pitch
* slice
+ level_w
)
799 res
->bo_width
= slice_pitch
* slice
+ level_w
;
800 if (lv
== templ
->last_level
)
801 res
->bo_height
= (level_y
- slice_qpitch
) + level_h
;
806 * Guess the texture size. For large textures, the errors are relative small.
809 guess_tex_size(const struct pipe_resource
*templ
,
810 enum intel_tiling_mode tiling
)
812 int bo_width
, bo_height
, bo_stride
;
814 /* HALIGN_8 and VALIGN_4 */
815 bo_width
= align(templ
->width0
, 8);
816 bo_height
= align(templ
->height0
, 4);
818 if (templ
->target
== PIPE_TEXTURE_3D
) {
819 const int num_rows
= util_next_power_of_two(templ
->depth0
);
822 sum
= bo_height
* templ
->depth0
;
823 for (lv
= 1; lv
<= templ
->last_level
; lv
++)
824 sum
+= u_minify(bo_height
, lv
) * u_minify(num_rows
, lv
);
828 else if (templ
->last_level
> 0) {
829 /* MIPLAYOUT_BELOW, ignore qpich */
830 bo_height
= (bo_height
+ u_minify(bo_height
, 1)) * templ
->array_size
;
833 bo_stride
= util_format_get_stride(templ
->format
, bo_width
);
837 bo_stride
= align(bo_stride
, 512);
838 bo_height
= align(bo_height
, 8);
841 bo_stride
= align(bo_stride
, 128);
842 bo_height
= align(bo_height
, 32);
845 bo_height
= align(bo_height
, 2);
849 return util_format_get_2d_size(templ
->format
, bo_stride
, bo_height
);
852 static enum intel_tiling_mode
853 get_tex_tiling(const struct ilo_resource
*res
)
855 const struct pipe_resource
*templ
= &res
->base
;
858 * From the Sandy Bridge PRM, volume 1 part 2, page 32:
860 * "Display/Overlay Y-Major not supported.
861 * X-Major required for Async Flips"
863 if (unlikely(templ
->bind
& PIPE_BIND_SCANOUT
))
864 return INTEL_TILING_X
;
867 * From the Sandy Bridge PRM, volume 3 part 2, page 158:
869 * "The cursor surface address must be 4K byte aligned. The cursor must
870 * be in linear memory, it cannot be tiled."
872 if (unlikely(templ
->bind
& PIPE_BIND_CURSOR
))
873 return INTEL_TILING_NONE
;
876 * From the Sandy Bridge PRM, volume 2 part 1, page 318:
878 * "[DevSNB+]: This field (Tiled Surface) must be set to TRUE. Linear
879 * Depth Buffer is not supported."
881 * "The Depth Buffer, if tiled, must use Y-Major tiling."
883 if (templ
->bind
& PIPE_BIND_DEPTH_STENCIL
)
884 return INTEL_TILING_Y
;
886 if (templ
->bind
& (PIPE_BIND_RENDER_TARGET
| PIPE_BIND_SAMPLER_VIEW
)) {
887 enum intel_tiling_mode tiling
= INTEL_TILING_NONE
;
890 * From the Sandy Bridge PRM, volume 1 part 2, page 32:
892 * "NOTE: 128BPE Format Color buffer ( render target ) MUST be
893 * either TileX or Linear."
895 * Also, heuristically set a minimum width/height for enabling tiling.
897 if (util_format_get_blocksizebits(templ
->format
) == 128 &&
898 (templ
->bind
& PIPE_BIND_RENDER_TARGET
) && templ
->width0
>= 64)
899 tiling
= INTEL_TILING_X
;
900 else if ((templ
->width0
>= 32 && templ
->height0
>= 16) ||
901 (templ
->width0
>= 16 && templ
->height0
>= 32))
902 tiling
= INTEL_TILING_Y
;
904 /* make sure the bo can be mapped through GTT if tiled */
905 if (tiling
!= INTEL_TILING_NONE
) {
907 * Usually only the first 256MB of the GTT is mappable.
909 * See also how intel_context::max_gtt_map_object_size is calculated.
911 const size_t mappable_gtt_size
= 256 * 1024 * 1024;
912 const size_t size
= guess_tex_size(templ
, tiling
);
914 /* be conservative */
915 if (size
> mappable_gtt_size
/ 4)
916 tiling
= INTEL_TILING_NONE
;
922 return INTEL_TILING_NONE
;
926 init_texture(struct ilo_resource
*res
)
928 const enum pipe_format format
= res
->base
.format
;
929 struct layout_tex_info info
;
931 /* determine tiling first as it may affect the layout */
932 res
->tiling
= get_tex_tiling(res
);
934 layout_tex_init(res
, &info
);
936 res
->compressed
= info
.compressed
;
937 res
->block_width
= info
.block_width
;
938 res
->block_height
= info
.block_height
;
939 res
->halign_8
= (info
.align_i
== 8);
940 res
->valign_4
= (info
.align_j
== 4);
942 switch (res
->base
.target
) {
943 case PIPE_TEXTURE_1D
:
944 case PIPE_TEXTURE_2D
:
945 case PIPE_TEXTURE_CUBE
:
946 case PIPE_TEXTURE_RECT
:
947 case PIPE_TEXTURE_1D_ARRAY
:
948 case PIPE_TEXTURE_2D_ARRAY
:
949 case PIPE_TEXTURE_CUBE_ARRAY
:
950 layout_tex_2d(res
, &info
);
952 case PIPE_TEXTURE_3D
:
953 layout_tex_3d(res
, &info
);
956 assert(!"unknown resource target");
961 assert(res
->bo_width
% info
.block_width
== 0);
962 assert(res
->bo_height
% info
.block_height
== 0);
963 res
->bo_width
/= info
.block_width
;
964 res
->bo_height
/= info
.block_height
;
965 res
->bo_cpp
= util_format_get_blocksize(format
);
969 init_buffer(struct ilo_resource
*res
)
971 res
->compressed
= false;
972 res
->block_width
= 1;
973 res
->block_height
= 1;
974 res
->halign_8
= false;
975 res
->valign_4
= false;
977 res
->bo_width
= res
->base
.width0
;
981 res
->tiling
= INTEL_TILING_NONE
;
984 static struct pipe_resource
*
985 create_resource(struct pipe_screen
*screen
,
986 const struct pipe_resource
*templ
,
987 struct winsys_handle
*handle
)
989 struct ilo_resource
*res
;
991 res
= CALLOC_STRUCT(ilo_resource
);
996 res
->base
.screen
= screen
;
997 pipe_reference_init(&res
->base
.reference
, 1);
998 res
->handle
= handle
;
1000 if (!alloc_slice_offsets(res
)) {
1005 if (templ
->target
== PIPE_BUFFER
)
1010 if (!realloc_bo(res
)) {
1011 free_slice_offsets(res
);
1020 ilo_can_create_resource(struct pipe_screen
*screen
,
1021 const struct pipe_resource
*templ
)
1024 * We do not know if we will fail until we try to allocate the bo.
1025 * So just set a limit on the texture size.
1027 const size_t max_size
= 1 * 1024 * 1024 * 1024;
1028 const size_t size
= guess_tex_size(templ
, INTEL_TILING_Y
);
1030 return (size
<= max_size
);
1033 static struct pipe_resource
*
1034 ilo_resource_create(struct pipe_screen
*screen
,
1035 const struct pipe_resource
*templ
)
1037 return create_resource(screen
, templ
, NULL
);
1040 static struct pipe_resource
*
1041 ilo_resource_from_handle(struct pipe_screen
*screen
,
1042 const struct pipe_resource
*templ
,
1043 struct winsys_handle
*handle
)
1045 return create_resource(screen
, templ
, handle
);
1049 ilo_resource_get_handle(struct pipe_screen
*screen
,
1050 struct pipe_resource
*r
,
1051 struct winsys_handle
*handle
)
1053 struct ilo_resource
*res
= ilo_resource(r
);
1056 err
= res
->bo
->export_handle(res
->bo
, handle
);
1062 ilo_resource_destroy(struct pipe_screen
*screen
,
1063 struct pipe_resource
*r
)
1065 struct ilo_resource
*res
= ilo_resource(r
);
1067 free_slice_offsets(res
);
1068 res
->bo
->unreference(res
->bo
);
1073 * Initialize resource-related functions.
1076 ilo_init_resource_functions(struct ilo_screen
*is
)
1078 is
->base
.can_create_resource
= ilo_can_create_resource
;
1079 is
->base
.resource_create
= ilo_resource_create
;
1080 is
->base
.resource_from_handle
= ilo_resource_from_handle
;
1081 is
->base
.resource_get_handle
= ilo_resource_get_handle
;
1082 is
->base
.resource_destroy
= ilo_resource_destroy
;
1086 * Initialize transfer-related functions.
1089 ilo_init_transfer_functions(struct ilo_context
*ilo
)
1091 ilo
->base
.transfer_map
= ilo_transfer_map
;
1092 ilo
->base
.transfer_flush_region
= ilo_transfer_flush_region
;
1093 ilo
->base
.transfer_unmap
= ilo_transfer_unmap
;
1094 ilo
->base
.transfer_inline_write
= ilo_transfer_inline_write
;
1098 * Return the offset (in bytes) to a slice within the bo.
1100 * When tile_aligned is true, the offset is to the tile containing the start
1101 * address of the slice. x_offset and y_offset are offsets (in pixels) from
1102 * the tile start to slice start. x_offset is always a multiple of 4 and
1103 * y_offset is always a multiple of 2.
1106 ilo_resource_get_slice_offset(const struct ilo_resource
*res
,
1107 int level
, int slice
, bool tile_aligned
,
1108 unsigned *x_offset
, unsigned *y_offset
)
1110 const unsigned x
= res
->slice_offsets
[level
][slice
].x
/ res
->block_width
;
1111 const unsigned y
= res
->slice_offsets
[level
][slice
].y
/ res
->block_height
;
1112 unsigned tile_w
, tile_h
, tile_size
, row_size
;
1113 unsigned slice_offset
;
1115 /* see the Sandy Bridge PRM, volume 1 part 2, page 24 */
1117 switch (res
->tiling
) {
1118 case INTEL_TILING_NONE
:
1119 tile_w
= res
->bo_cpp
;
1122 case INTEL_TILING_X
:
1126 case INTEL_TILING_Y
:
1131 assert(!"unknown tiling");
1132 tile_w
= res
->bo_cpp
;
1137 tile_size
= tile_w
* tile_h
;
1138 row_size
= res
->bo_stride
* tile_h
;
1141 * for non-tiled resources, this is equivalent to
1143 * slice_offset = y * res->bo_stride + x * res->bo_cpp;
1146 row_size
* (y
/ tile_h
) + tile_size
* (x
* res
->bo_cpp
/ tile_w
);
1149 * Since res->bo_stride is a multiple of tile_w, slice_offset should be
1150 * aligned at this point.
1152 assert(slice_offset
% tile_size
== 0);
1156 * because of the possible values of align_i and align_j in
1157 * layout_tex_init(), x_offset must be a multiple of 4 and y_offset must
1158 * be a multiple of 2.
1161 assert(tile_w
% res
->bo_cpp
== 0);
1162 *x_offset
= (x
% (tile_w
/ res
->bo_cpp
)) * res
->block_width
;
1163 assert(*x_offset
% 4 == 0);
1166 *y_offset
= (y
% tile_h
) * res
->block_height
;
1167 assert(*y_offset
% 2 == 0);
1171 const unsigned tx
= (x
* res
->bo_cpp
) % tile_w
;
1172 const unsigned ty
= y
% tile_h
;
1174 switch (res
->tiling
) {
1175 case INTEL_TILING_NONE
:
1176 assert(tx
== 0 && ty
== 0);
1178 case INTEL_TILING_X
:
1179 slice_offset
+= tile_w
* ty
+ tx
;
1181 case INTEL_TILING_Y
:
1182 slice_offset
+= tile_h
* 16 * (tx
/ 16) + ty
* 16 + (tx
% 16);
1192 return slice_offset
;