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_surface.h"
29 #include "util/u_transfer.h"
30 #include "util/u_format_etc.h"
33 #include "ilo_context.h"
34 #include "ilo_resource.h"
35 #include "ilo_transfer.h"
37 enum ilo_transfer_map_method
{
38 /* map() / map_gtt() / map_unsynchronized() */
41 ILO_TRANSFER_MAP_UNSYNC
,
43 /* use staging system buffer */
44 ILO_TRANSFER_MAP_SW_CONVERT
,
45 ILO_TRANSFER_MAP_SW_ZS
,
49 struct pipe_transfer base
;
51 enum ilo_transfer_map_method method
;
57 static inline struct ilo_transfer
*
58 ilo_transfer(struct pipe_transfer
*transfer
)
60 return (struct ilo_transfer
*) transfer
;
64 is_bo_busy(struct ilo_context
*ilo
, struct intel_bo
*bo
, bool *need_flush
)
66 const bool referenced
= ilo
->cp
->bo
->references(ilo
->cp
->bo
, bo
);
69 *need_flush
= referenced
;
75 * XXX With hardware context support, the bo may be needed by GPU
76 * without being referenced by ilo->cp->bo. We have to flush
77 * unconditionally, and that is bad.
79 if (ilo
->cp
->render_ctx
)
80 ilo_cp_flush(ilo
->cp
);
82 return intel_bo_is_busy(bo
);
86 map_bo_for_transfer(struct ilo_context
*ilo
, struct intel_bo
*bo
,
87 const struct ilo_transfer
*xfer
)
91 switch (xfer
->method
) {
92 case ILO_TRANSFER_MAP_CPU
:
93 err
= bo
->map(bo
, (xfer
->base
.usage
& PIPE_TRANSFER_WRITE
));
95 case ILO_TRANSFER_MAP_GTT
:
96 err
= bo
->map_gtt(bo
);
98 case ILO_TRANSFER_MAP_UNSYNC
:
99 err
= bo
->map_unsynchronized(bo
);
102 assert(!"unknown mapping method");
111 * Choose the best mapping method, depending on the transfer usage and whether
115 choose_transfer_method(struct ilo_context
*ilo
, struct ilo_transfer
*xfer
)
117 struct pipe_resource
*res
= xfer
->base
.resource
;
118 const unsigned usage
= xfer
->base
.usage
;
119 /* prefer map() when there is the last-level cache */
120 const bool prefer_cpu
=
121 (ilo
->dev
->has_llc
|| (usage
& PIPE_TRANSFER_READ
));
122 struct ilo_texture
*tex
;
123 struct ilo_buffer
*buf
;
125 bool tiled
, need_flush
;
127 if (res
->target
== PIPE_BUFFER
) {
130 buf
= ilo_buffer(res
);
137 tex
= ilo_texture(res
);
139 tiled
= (tex
->tiling
!= INTEL_TILING_NONE
);
142 /* choose between mapping through CPU or GTT */
143 if (usage
& PIPE_TRANSFER_MAP_DIRECTLY
) {
144 /* we do not want fencing */
145 if (tiled
|| prefer_cpu
)
146 xfer
->method
= ILO_TRANSFER_MAP_CPU
;
148 xfer
->method
= ILO_TRANSFER_MAP_GTT
;
151 if (!tiled
&& prefer_cpu
)
152 xfer
->method
= ILO_TRANSFER_MAP_CPU
;
154 xfer
->method
= ILO_TRANSFER_MAP_GTT
;
157 /* see if we can avoid stalling */
158 if (is_bo_busy(ilo
, bo
, &need_flush
)) {
159 bool will_stall
= true;
161 if (usage
& PIPE_TRANSFER_MAP_DIRECTLY
) {
162 /* nothing we can do */
164 else if (usage
& PIPE_TRANSFER_UNSYNCHRONIZED
) {
165 /* unsynchronized gtt mapping does not stall */
166 xfer
->method
= ILO_TRANSFER_MAP_UNSYNC
;
169 else if (usage
& PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE
) {
170 /* discard old bo and allocate a new one for mapping */
171 if ((tex
&& ilo_texture_alloc_bo(tex
)) ||
172 (buf
&& ilo_buffer_alloc_bo(buf
)))
175 else if (usage
& PIPE_TRANSFER_FLUSH_EXPLICIT
) {
177 * We could allocate and return a system buffer here. When a region of
178 * the buffer is explicitly flushed, we pwrite() the region to a
179 * temporary bo and emit pipelined copy blit.
181 * For now, do nothing.
184 else if (usage
& PIPE_TRANSFER_DISCARD_RANGE
) {
186 * We could allocate a temporary bo for mapping, and emit pipelined copy
187 * blit upon unmapping.
189 * For now, do nothing.
194 if (usage
& PIPE_TRANSFER_DONTBLOCK
)
197 /* flush to make bo busy (so that map() stalls as it should be) */
199 ilo_cp_flush(ilo
->cp
);
203 if (tex
&& !(usage
& PIPE_TRANSFER_MAP_DIRECTLY
)) {
204 if (tex
->separate_s8
|| tex
->bo_format
== PIPE_FORMAT_S8_UINT
)
205 xfer
->method
= ILO_TRANSFER_MAP_SW_ZS
;
206 /* need to convert on-the-fly */
207 else if (tex
->bo_format
!= tex
->base
.format
)
208 xfer
->method
= ILO_TRANSFER_MAP_SW_CONVERT
;
215 tex_get_box_origin(const struct ilo_texture
*tex
,
216 unsigned level
, unsigned slice
,
217 const struct pipe_box
*box
,
218 unsigned *mem_x
, unsigned *mem_y
)
222 x
= tex
->slice_offsets
[level
][slice
+ box
->z
].x
+ box
->x
;
223 y
= tex
->slice_offsets
[level
][slice
+ box
->z
].y
+ box
->y
;
225 assert(x
% tex
->block_width
== 0 && y
% tex
->block_height
== 0);
227 *mem_x
= x
/ tex
->block_width
* tex
->bo_cpp
;
228 *mem_y
= y
/ tex
->block_height
;
232 tex_get_box_offset(const struct ilo_texture
*tex
, unsigned level
,
233 const struct pipe_box
*box
)
235 unsigned mem_x
, mem_y
;
237 tex_get_box_origin(tex
, level
, 0, box
, &mem_x
, &mem_y
);
239 return mem_y
* tex
->bo_stride
+ mem_x
;
243 tex_get_slice_stride(const struct ilo_texture
*tex
, unsigned level
)
247 /* there is no 3D array texture */
248 assert(tex
->base
.array_size
== 1 || tex
->base
.depth0
== 1);
250 if (tex
->base
.array_size
== 1) {
251 /* non-array, non-3D */
252 if (tex
->base
.depth0
== 1)
255 /* only the first level has a fixed slice stride */
257 assert(!"no slice stride for 3D texture with level > 0");
262 qpitch
= tex
->slice_offsets
[level
][1].y
- tex
->slice_offsets
[level
][0].y
;
263 assert(qpitch
% tex
->block_height
== 0);
265 return (qpitch
/ tex
->block_height
) * tex
->bo_stride
;
269 tex_tile_x_swizzle(unsigned addr
)
272 * From the Ivy Bridge PRM, volume 1 part 2, page 24:
274 * "As shown in the tiling algorithm, the new address bit[6] should be:
276 * Address bit[6] <= TiledAddr bit[6] XOR
277 * TiledAddr bit[9] XOR
280 return addr
^ (((addr
>> 3) ^ (addr
>> 4)) & 0x40);
284 tex_tile_y_swizzle(unsigned addr
)
287 * From the Ivy Bridge PRM, volume 1 part 2, page 24:
289 * "As shown in the tiling algorithm, The new address bit[6] becomes:
291 * Address bit[6] <= TiledAddr bit[6] XOR
294 return addr
^ ((addr
>> 3) & 0x40);
298 tex_tile_x_offset(unsigned mem_x
, unsigned mem_y
,
299 unsigned tiles_per_row
, bool swizzle
)
302 * From the Sandy Bridge PRM, volume 1 part 2, page 21, we know that a
303 * X-major tile has 8 rows and 32 OWord columns (512 bytes). Tiles in the
304 * tiled region are numbered in row-major order, starting from zero. The
305 * tile number can thus be calculated as follows:
307 * tile = (mem_y / 8) * tiles_per_row + (mem_x / 512)
309 * OWords in that tile are also numbered in row-major order, starting from
310 * zero. The OWord number can thus be calculated as follows:
312 * oword = (mem_y % 8) * 32 + ((mem_x % 512) / 16)
314 * and the tiled offset is
316 * offset = tile * 4096 + oword * 16 + (mem_x % 16)
317 * = tile * 4096 + (mem_y % 8) * 512 + (mem_x % 512)
319 unsigned tile
, offset
;
321 tile
= (mem_y
>> 3) * tiles_per_row
+ (mem_x
>> 9);
322 offset
= tile
<< 12 | (mem_y
& 0x7) << 9 | (mem_x
& 0x1ff);
324 return (swizzle
) ? tex_tile_x_swizzle(offset
) : offset
;
328 tex_tile_y_offset(unsigned mem_x
, unsigned mem_y
,
329 unsigned tiles_per_row
, bool swizzle
)
332 * From the Sandy Bridge PRM, volume 1 part 2, page 22, we know that a
333 * Y-major tile has 32 rows and 8 OWord columns (128 bytes). Tiles in the
334 * tiled region are numbered in row-major order, starting from zero. The
335 * tile number can thus be calculated as follows:
337 * tile = (mem_y / 32) * tiles_per_row + (mem_x / 128)
339 * OWords in that tile are numbered in column-major order, starting from
340 * zero. The OWord number can thus be calculated as follows:
342 * oword = ((mem_x % 128) / 16) * 32 + (mem_y % 32)
344 * and the tiled offset is
346 * offset = tile * 4096 + oword * 16 + (mem_x % 16)
348 unsigned tile
, oword
, offset
;
350 tile
= (mem_y
>> 5) * tiles_per_row
+ (mem_x
>> 7);
351 oword
= (mem_x
& 0x70) << 1 | (mem_y
& 0x1f);
352 offset
= tile
<< 12 | oword
<< 4 | (mem_x
& 0xf);
354 return (swizzle
) ? tex_tile_y_swizzle(offset
) : offset
;
358 tex_tile_w_offset(unsigned mem_x
, unsigned mem_y
,
359 unsigned tiles_per_row
, bool swizzle
)
362 * From the Sandy Bridge PRM, volume 1 part 2, page 23, we know that a
363 * W-major tile has 8 8x8-block rows and 8 8x8-block columns. Tiles in the
364 * tiled region are numbered in row-major order, starting from zero. The
365 * tile number can thus be calculated as follows:
367 * tile = (mem_y / 64) * tiles_per_row + (mem_x / 64)
369 * 8x8-blocks in that tile are numbered in column-major order, starting
370 * from zero. The 8x8-block number can thus be calculated as follows:
372 * blk8 = ((mem_x % 64) / 8) * 8 + ((mem_y % 64) / 8)
374 * Each 8x8-block is divided into 4 4x4-blocks, in row-major order. Each
375 * 4x4-block is further divided into 4 2x2-blocks, also in row-major order.
378 * blk4 = (((mem_y % 64) / 4) & 1) * 2 + (((mem_x % 64) / 4) & 1)
379 * blk2 = (((mem_y % 64) / 2) & 1) * 2 + (((mem_x % 64) / 2) & 1)
380 * blk1 = (((mem_y % 64) ) & 1) * 2 + (((mem_x % 64) ) & 1)
382 * and the tiled offset is
384 * offset = tile * 4096 + blk8 * 64 + blk4 * 16 + blk2 * 4 + blk1
386 unsigned tile
, blk8
, blk4
, blk2
, blk1
, offset
;
388 tile
= (mem_y
>> 6) * tiles_per_row
+ (mem_x
>> 6);
389 blk8
= ((mem_x
>> 3) & 0x7) << 3 | ((mem_y
>> 3) & 0x7);
390 blk4
= ((mem_y
>> 2) & 0x1) << 1 | ((mem_x
>> 2) & 0x1);
391 blk2
= ((mem_y
>> 1) & 0x1) << 1 | ((mem_x
>> 1) & 0x1);
392 blk1
= ((mem_y
) & 0x1) << 1 | ((mem_x
) & 0x1);
393 offset
= tile
<< 12 | blk8
<< 6 | blk4
<< 4 | blk2
<< 2 | blk1
;
395 return (swizzle
) ? tex_tile_y_swizzle(offset
) : offset
;
399 tex_tile_none_offset(unsigned mem_x
, unsigned mem_y
,
400 unsigned tiles_per_row
, bool swizzle
)
402 return mem_y
* tiles_per_row
+ mem_x
;
405 typedef unsigned (*tex_tile_offset_func
)(unsigned mem_x
, unsigned mem_y
,
406 unsigned tiles_per_row
,
409 static tex_tile_offset_func
410 tex_tile_choose_offset_func(const struct ilo_texture
*tex
,
411 unsigned *tiles_per_row
)
413 switch (tex
->tiling
) {
415 *tiles_per_row
= tex
->bo_stride
/ 512;
416 return tex_tile_x_offset
;
418 *tiles_per_row
= tex
->bo_stride
/ 128;
419 return tex_tile_y_offset
;
420 case INTEL_TILING_NONE
:
423 if (tex
->bo_format
== PIPE_FORMAT_S8_UINT
) {
424 *tiles_per_row
= tex
->bo_stride
/ 64;
425 return tex_tile_w_offset
;
428 *tiles_per_row
= tex
->bo_stride
;
429 return tex_tile_none_offset
;
435 tex_staging_sys_zs_read(struct ilo_context
*ilo
,
436 struct ilo_texture
*tex
,
437 const struct ilo_transfer
*xfer
)
439 const bool swizzle
= ilo
->dev
->has_address_swizzling
;
440 const struct pipe_box
*box
= &xfer
->base
.box
;
441 const uint8_t *src
= tex
->bo
->get_virtual(tex
->bo
);
442 tex_tile_offset_func tile_offset
;
443 unsigned tiles_per_row
;
446 tile_offset
= tex_tile_choose_offset_func(tex
, &tiles_per_row
);
448 assert(tex
->block_width
== 1 && tex
->block_height
== 1);
450 if (tex
->separate_s8
) {
451 struct ilo_texture
*s8_tex
= tex
->separate_s8
;
452 const uint8_t *s8_src
= s8_tex
->bo
->get_virtual(s8_tex
->bo
);
453 tex_tile_offset_func s8_tile_offset
;
454 unsigned s8_tiles_per_row
;
455 int dst_cpp
, dst_s8_pos
, src_cpp_used
;
457 s8_tile_offset
= tex_tile_choose_offset_func(s8_tex
, &s8_tiles_per_row
);
459 if (tex
->base
.format
== PIPE_FORMAT_Z24_UNORM_S8_UINT
) {
460 assert(tex
->bo_format
== PIPE_FORMAT_Z24X8_UNORM
);
467 assert(tex
->base
.format
== PIPE_FORMAT_Z32_FLOAT_S8X24_UINT
);
468 assert(tex
->bo_format
== PIPE_FORMAT_Z32_FLOAT
);
475 for (slice
= 0; slice
< box
->depth
; slice
++) {
476 unsigned mem_x
, mem_y
, s8_mem_x
, s8_mem_y
;
480 tex_get_box_origin(tex
, xfer
->base
.level
, slice
,
481 box
, &mem_x
, &mem_y
);
482 tex_get_box_origin(s8_tex
, xfer
->base
.level
, slice
,
483 box
, &s8_mem_x
, &s8_mem_y
);
485 dst
= xfer
->staging_sys
+ xfer
->base
.layer_stride
* slice
;
487 for (i
= 0; i
< box
->height
; i
++) {
488 unsigned x
= mem_x
, s8_x
= s8_mem_x
;
491 for (j
= 0; j
< box
->width
; j
++) {
492 const unsigned offset
=
493 tile_offset(x
, mem_y
, tiles_per_row
, swizzle
);
494 const unsigned s8_offset
=
495 s8_tile_offset(s8_x
, s8_mem_y
, s8_tiles_per_row
, swizzle
);
497 memcpy(d
, src
+ offset
, src_cpp_used
);
498 d
[dst_s8_pos
] = s8_src
[s8_offset
];
505 dst
+= xfer
->base
.stride
;
512 assert(tex
->bo_format
== PIPE_FORMAT_S8_UINT
);
514 for (slice
= 0; slice
< box
->depth
; slice
++) {
515 unsigned mem_x
, mem_y
;
519 tex_get_box_origin(tex
, xfer
->base
.level
, slice
,
520 box
, &mem_x
, &mem_y
);
522 dst
= xfer
->staging_sys
+ xfer
->base
.layer_stride
* slice
;
524 for (i
= 0; i
< box
->height
; i
++) {
528 for (j
= 0; j
< box
->width
; j
++) {
529 const unsigned offset
=
530 tile_offset(x
, mem_y
, tiles_per_row
, swizzle
);
538 dst
+= xfer
->base
.stride
;
546 tex_staging_sys_zs_write(struct ilo_context
*ilo
,
547 struct ilo_texture
*tex
,
548 const struct ilo_transfer
*xfer
)
550 const bool swizzle
= ilo
->dev
->has_address_swizzling
;
551 const struct pipe_box
*box
= &xfer
->base
.box
;
552 uint8_t *dst
= tex
->bo
->get_virtual(tex
->bo
);
553 tex_tile_offset_func tile_offset
;
554 unsigned tiles_per_row
;
557 tile_offset
= tex_tile_choose_offset_func(tex
, &tiles_per_row
);
559 assert(tex
->block_width
== 1 && tex
->block_height
== 1);
561 if (tex
->separate_s8
) {
562 struct ilo_texture
*s8_tex
= tex
->separate_s8
;
563 uint8_t *s8_dst
= s8_tex
->bo
->get_virtual(s8_tex
->bo
);
564 tex_tile_offset_func s8_tile_offset
;
565 unsigned s8_tiles_per_row
;
566 int src_cpp
, src_s8_pos
, dst_cpp_used
;
568 s8_tile_offset
= tex_tile_choose_offset_func(s8_tex
, &s8_tiles_per_row
);
570 if (tex
->base
.format
== PIPE_FORMAT_Z24_UNORM_S8_UINT
) {
571 assert(tex
->bo_format
== PIPE_FORMAT_Z24X8_UNORM
);
578 assert(tex
->base
.format
== PIPE_FORMAT_Z32_FLOAT_S8X24_UINT
);
579 assert(tex
->bo_format
== PIPE_FORMAT_Z32_FLOAT
);
586 for (slice
= 0; slice
< box
->depth
; slice
++) {
587 unsigned mem_x
, mem_y
, s8_mem_x
, s8_mem_y
;
591 tex_get_box_origin(tex
, xfer
->base
.level
, slice
,
592 box
, &mem_x
, &mem_y
);
593 tex_get_box_origin(s8_tex
, xfer
->base
.level
, slice
,
594 box
, &s8_mem_x
, &s8_mem_y
);
596 src
= xfer
->staging_sys
+ xfer
->base
.layer_stride
* slice
;
598 for (i
= 0; i
< box
->height
; i
++) {
599 unsigned x
= mem_x
, s8_x
= s8_mem_x
;
600 const uint8_t *s
= src
;
602 for (j
= 0; j
< box
->width
; j
++) {
603 const unsigned offset
=
604 tile_offset(x
, mem_y
, tiles_per_row
, swizzle
);
605 const unsigned s8_offset
=
606 s8_tile_offset(s8_x
, s8_mem_y
, s8_tiles_per_row
, swizzle
);
608 memcpy(dst
+ offset
, s
, dst_cpp_used
);
609 s8_dst
[s8_offset
] = s
[src_s8_pos
];
616 src
+= xfer
->base
.stride
;
623 assert(tex
->bo_format
== PIPE_FORMAT_S8_UINT
);
625 for (slice
= 0; slice
< box
->depth
; slice
++) {
626 unsigned mem_x
, mem_y
;
630 tex_get_box_origin(tex
, xfer
->base
.level
, slice
,
631 box
, &mem_x
, &mem_y
);
633 src
= xfer
->staging_sys
+ xfer
->base
.layer_stride
* slice
;
635 for (i
= 0; i
< box
->height
; i
++) {
637 const uint8_t *s
= src
;
639 for (j
= 0; j
< box
->width
; j
++) {
640 const unsigned offset
=
641 tile_offset(x
, mem_y
, tiles_per_row
, swizzle
);
649 src
+= xfer
->base
.stride
;
657 tex_staging_sys_convert_write(struct ilo_context
*ilo
,
658 struct ilo_texture
*tex
,
659 const struct ilo_transfer
*xfer
)
661 const struct pipe_box
*box
= &xfer
->base
.box
;
662 unsigned dst_slice_stride
;
666 dst
= tex
->bo
->get_virtual(tex
->bo
);
667 dst
+= tex_get_box_offset(tex
, xfer
->base
.level
, box
);
669 /* slice stride is not always available */
671 dst_slice_stride
= tex_get_slice_stride(tex
, xfer
->base
.level
);
673 dst_slice_stride
= 0;
675 if (unlikely(tex
->bo_format
== tex
->base
.format
)) {
676 util_copy_box(dst
, tex
->bo_format
, tex
->bo_stride
, dst_slice_stride
,
677 0, 0, 0, box
->width
, box
->height
, box
->depth
,
678 xfer
->staging_sys
, xfer
->base
.stride
, xfer
->base
.layer_stride
,
683 switch (tex
->base
.format
) {
684 case PIPE_FORMAT_ETC1_RGB8
:
685 assert(tex
->bo_format
== PIPE_FORMAT_R8G8B8X8_UNORM
);
687 for (slice
= 0; slice
< box
->depth
; slice
++) {
689 xfer
->staging_sys
+ xfer
->base
.layer_stride
* slice
;
691 util_format_etc1_rgb8_unpack_rgba_8unorm(dst
,
692 tex
->bo_stride
, src
, xfer
->base
.stride
,
693 box
->width
, box
->height
);
695 dst
+= dst_slice_stride
;
699 assert(!"unable to convert the staging data");
705 tex_staging_sys_map_bo(const struct ilo_context
*ilo
,
706 const struct ilo_texture
*tex
,
707 bool for_read_back
, bool linear_view
)
709 const bool prefer_cpu
= (ilo
->dev
->has_llc
|| for_read_back
);
712 if (prefer_cpu
&& (tex
->tiling
== INTEL_TILING_NONE
|| !linear_view
))
713 err
= tex
->bo
->map(tex
->bo
, !for_read_back
);
715 err
= tex
->bo
->map_gtt(tex
->bo
);
717 if (!tex
->separate_s8
)
720 err
= tex
->separate_s8
->bo
->map(tex
->separate_s8
->bo
, !for_read_back
);
722 tex
->bo
->unmap(tex
->bo
);
728 tex_staging_sys_unmap_bo(const struct ilo_context
*ilo
,
729 const struct ilo_texture
*tex
)
731 if (tex
->separate_s8
)
732 tex
->separate_s8
->bo
->unmap(tex
->separate_s8
->bo
);
734 tex
->bo
->unmap(tex
->bo
);
738 tex_staging_sys_unmap(struct ilo_context
*ilo
,
739 struct ilo_texture
*tex
,
740 struct ilo_transfer
*xfer
)
744 if (!(xfer
->base
.usage
& PIPE_TRANSFER_WRITE
)) {
745 FREE(xfer
->staging_sys
);
749 switch (xfer
->method
) {
750 case ILO_TRANSFER_MAP_SW_CONVERT
:
751 success
= tex_staging_sys_map_bo(ilo
, tex
, false, true);
753 tex_staging_sys_convert_write(ilo
, tex
, xfer
);
754 tex_staging_sys_unmap_bo(ilo
, tex
);
757 case ILO_TRANSFER_MAP_SW_ZS
:
758 success
= tex_staging_sys_map_bo(ilo
, tex
, false, false);
760 tex_staging_sys_zs_write(ilo
, tex
, xfer
);
761 tex_staging_sys_unmap_bo(ilo
, tex
);
765 assert(!"unknown mapping method");
771 ilo_err("failed to map resource for moving staging data\n");
773 FREE(xfer
->staging_sys
);
777 tex_staging_sys_map(struct ilo_context
*ilo
,
778 struct ilo_texture
*tex
,
779 struct ilo_transfer
*xfer
)
781 const struct pipe_box
*box
= &xfer
->base
.box
;
782 const size_t stride
= util_format_get_stride(tex
->base
.format
, box
->width
);
784 util_format_get_2d_size(tex
->base
.format
, stride
, box
->height
);
785 bool read_back
= false, success
;
787 xfer
->staging_sys
= MALLOC(size
* box
->depth
);
788 if (!xfer
->staging_sys
)
791 xfer
->base
.stride
= stride
;
792 xfer
->base
.layer_stride
= size
;
793 xfer
->ptr
= xfer
->staging_sys
;
795 /* see if we need to read the resource back */
796 if (xfer
->base
.usage
& PIPE_TRANSFER_READ
) {
799 else if (xfer
->base
.usage
& PIPE_TRANSFER_WRITE
) {
800 const unsigned discard_flags
=
801 (PIPE_TRANSFER_DISCARD_RANGE
| PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE
);
803 if (!(xfer
->base
.usage
& discard_flags
))
810 switch (xfer
->method
) {
811 case ILO_TRANSFER_MAP_SW_CONVERT
:
812 assert(!"no on-the-fly format conversion for mapping");
815 case ILO_TRANSFER_MAP_SW_ZS
:
816 success
= tex_staging_sys_map_bo(ilo
, tex
, true, false);
818 tex_staging_sys_zs_read(ilo
, tex
, xfer
);
819 tex_staging_sys_unmap_bo(ilo
, tex
);
823 assert(!"unknown mapping method");
832 tex_direct_unmap(struct ilo_context
*ilo
,
833 struct ilo_texture
*tex
,
834 struct ilo_transfer
*xfer
)
836 tex
->bo
->unmap(tex
->bo
);
840 tex_direct_map(struct ilo_context
*ilo
,
841 struct ilo_texture
*tex
,
842 struct ilo_transfer
*xfer
)
844 if (!map_bo_for_transfer(ilo
, tex
->bo
, xfer
))
847 /* note that stride is for a block row, not a texel row */
848 xfer
->base
.stride
= tex
->bo_stride
;
850 /* slice stride is not always available */
851 if (xfer
->base
.box
.depth
> 1)
852 xfer
->base
.layer_stride
= tex_get_slice_stride(tex
, xfer
->base
.level
);
854 xfer
->base
.layer_stride
= 0;
856 xfer
->ptr
= tex
->bo
->get_virtual(tex
->bo
);
857 xfer
->ptr
+= tex_get_box_offset(tex
, xfer
->base
.level
, &xfer
->base
.box
);
863 tex_map(struct ilo_context
*ilo
, struct ilo_transfer
*xfer
)
865 struct ilo_texture
*tex
= ilo_texture(xfer
->base
.resource
);
868 if (!choose_transfer_method(ilo
, xfer
))
871 switch (xfer
->method
) {
872 case ILO_TRANSFER_MAP_CPU
:
873 case ILO_TRANSFER_MAP_GTT
:
874 case ILO_TRANSFER_MAP_UNSYNC
:
875 success
= tex_direct_map(ilo
, tex
, xfer
);
877 case ILO_TRANSFER_MAP_SW_CONVERT
:
878 case ILO_TRANSFER_MAP_SW_ZS
:
879 success
= tex_staging_sys_map(ilo
, tex
, xfer
);
882 assert(!"unknown mapping method");
891 tex_unmap(struct ilo_context
*ilo
, struct ilo_transfer
*xfer
)
893 struct ilo_texture
*tex
= ilo_texture(xfer
->base
.resource
);
895 switch (xfer
->method
) {
896 case ILO_TRANSFER_MAP_CPU
:
897 case ILO_TRANSFER_MAP_GTT
:
898 case ILO_TRANSFER_MAP_UNSYNC
:
899 tex_direct_unmap(ilo
, tex
, xfer
);
901 case ILO_TRANSFER_MAP_SW_CONVERT
:
902 case ILO_TRANSFER_MAP_SW_ZS
:
903 tex_staging_sys_unmap(ilo
, tex
, xfer
);
906 assert(!"unknown mapping method");
912 buf_map(struct ilo_context
*ilo
, struct ilo_transfer
*xfer
)
914 struct ilo_buffer
*buf
= ilo_buffer(xfer
->base
.resource
);
916 if (!choose_transfer_method(ilo
, xfer
))
919 if (!map_bo_for_transfer(ilo
, buf
->bo
, xfer
))
922 assert(xfer
->base
.level
== 0);
923 assert(xfer
->base
.box
.y
== 0);
924 assert(xfer
->base
.box
.z
== 0);
925 assert(xfer
->base
.box
.height
== 1);
926 assert(xfer
->base
.box
.depth
== 1);
928 xfer
->base
.stride
= 0;
929 xfer
->base
.layer_stride
= 0;
931 xfer
->ptr
= buf
->bo
->get_virtual(buf
->bo
);
932 xfer
->ptr
+= xfer
->base
.box
.x
;
938 buf_unmap(struct ilo_context
*ilo
, struct ilo_transfer
*xfer
)
940 struct ilo_buffer
*buf
= ilo_buffer(xfer
->base
.resource
);
942 buf
->bo
->unmap(buf
->bo
);
946 buf_pwrite(struct ilo_context
*ilo
, struct ilo_buffer
*buf
,
947 unsigned usage
, int offset
, int size
, const void *data
)
951 /* see if we can avoid stalling */
952 if (is_bo_busy(ilo
, buf
->bo
, &need_flush
)) {
953 bool will_stall
= true;
955 if (usage
& PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE
) {
956 /* old data not needed so discard the old bo to avoid stalling */
957 if (ilo_buffer_alloc_bo(buf
))
962 * We could allocate a temporary bo to hold the data and emit
963 * pipelined copy blit to move them to buf->bo. But for now, do
968 /* flush to make bo busy (so that pwrite() stalls as it should be) */
969 if (will_stall
&& need_flush
)
970 ilo_cp_flush(ilo
->cp
);
973 buf
->bo
->pwrite(buf
->bo
, offset
, size
, data
);
977 ilo_transfer_flush_region(struct pipe_context
*pipe
,
978 struct pipe_transfer
*transfer
,
979 const struct pipe_box
*box
)
984 ilo_transfer_unmap(struct pipe_context
*pipe
,
985 struct pipe_transfer
*transfer
)
987 struct ilo_context
*ilo
= ilo_context(pipe
);
988 struct ilo_transfer
*xfer
= ilo_transfer(transfer
);
990 if (xfer
->base
.resource
->target
== PIPE_BUFFER
)
991 buf_unmap(ilo
, xfer
);
993 tex_unmap(ilo
, xfer
);
995 pipe_resource_reference(&xfer
->base
.resource
, NULL
);
1000 ilo_transfer_map(struct pipe_context
*pipe
,
1001 struct pipe_resource
*res
,
1004 const struct pipe_box
*box
,
1005 struct pipe_transfer
**transfer
)
1007 struct ilo_context
*ilo
= ilo_context(pipe
);
1008 struct ilo_transfer
*xfer
;
1011 xfer
= MALLOC_STRUCT(ilo_transfer
);
1017 xfer
->base
.resource
= NULL
;
1018 pipe_resource_reference(&xfer
->base
.resource
, res
);
1019 xfer
->base
.level
= level
;
1020 xfer
->base
.usage
= usage
;
1021 xfer
->base
.box
= *box
;
1023 if (res
->target
== PIPE_BUFFER
)
1024 success
= buf_map(ilo
, xfer
);
1026 success
= tex_map(ilo
, xfer
);
1029 pipe_resource_reference(&xfer
->base
.resource
, NULL
);
1035 *transfer
= &xfer
->base
;
1041 ilo_transfer_inline_write(struct pipe_context
*pipe
,
1042 struct pipe_resource
*res
,
1045 const struct pipe_box
*box
,
1048 unsigned layer_stride
)
1050 if (likely(res
->target
== PIPE_BUFFER
) &&
1051 !(usage
& PIPE_TRANSFER_UNSYNCHRONIZED
)) {
1052 /* they should specify just an offset and a size */
1054 assert(box
->y
== 0);
1055 assert(box
->z
== 0);
1056 assert(box
->height
== 1);
1057 assert(box
->depth
== 1);
1059 buf_pwrite(ilo_context(pipe
), ilo_buffer(res
),
1060 usage
, box
->x
, box
->width
, data
);
1063 u_default_transfer_inline_write(pipe
, res
,
1064 level
, usage
, box
, data
, stride
, layer_stride
);
1069 * Initialize transfer-related functions.
1072 ilo_init_transfer_functions(struct ilo_context
*ilo
)
1074 ilo
->base
.transfer_map
= ilo_transfer_map
;
1075 ilo
->base
.transfer_flush_region
= ilo_transfer_flush_region
;
1076 ilo
->base
.transfer_unmap
= ilo_transfer_unmap
;
1077 ilo
->base
.transfer_inline_write
= ilo_transfer_inline_write
;