1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker * Copyright 2010 Jerome Glisse <[email protected]>
3*61046927SAndroid Build Coastguard Worker * Copyright 2015-2021 Advanced Micro Devices, Inc.
4*61046927SAndroid Build Coastguard Worker * Copyright 2023 Valve Corporation
5*61046927SAndroid Build Coastguard Worker * All Rights Reserved.
6*61046927SAndroid Build Coastguard Worker *
7*61046927SAndroid Build Coastguard Worker * SPDX-License-Identifier: MIT
8*61046927SAndroid Build Coastguard Worker */
9*61046927SAndroid Build Coastguard Worker
10*61046927SAndroid Build Coastguard Worker #include "radv_sdma.h"
11*61046927SAndroid Build Coastguard Worker #include "util/macros.h"
12*61046927SAndroid Build Coastguard Worker #include "util/u_memory.h"
13*61046927SAndroid Build Coastguard Worker #include "radv_buffer.h"
14*61046927SAndroid Build Coastguard Worker #include "radv_cs.h"
15*61046927SAndroid Build Coastguard Worker #include "radv_formats.h"
16*61046927SAndroid Build Coastguard Worker
17*61046927SAndroid Build Coastguard Worker #include "ac_formats.h"
18*61046927SAndroid Build Coastguard Worker
19*61046927SAndroid Build Coastguard Worker struct radv_sdma_chunked_copy_info {
20*61046927SAndroid Build Coastguard Worker unsigned extent_horizontal_blocks;
21*61046927SAndroid Build Coastguard Worker unsigned extent_vertical_blocks;
22*61046927SAndroid Build Coastguard Worker unsigned aligned_row_pitch;
23*61046927SAndroid Build Coastguard Worker unsigned num_rows_per_copy;
24*61046927SAndroid Build Coastguard Worker };
25*61046927SAndroid Build Coastguard Worker
26*61046927SAndroid Build Coastguard Worker static const VkExtent3D radv_sdma_t2t_alignment_2d_and_planar[] = {
27*61046927SAndroid Build Coastguard Worker {16, 16, 1}, /* 1 bpp */
28*61046927SAndroid Build Coastguard Worker {16, 8, 1}, /* 2 bpp */
29*61046927SAndroid Build Coastguard Worker {8, 8, 1}, /* 4 bpp */
30*61046927SAndroid Build Coastguard Worker {8, 4, 1}, /* 8 bpp */
31*61046927SAndroid Build Coastguard Worker {4, 4, 1}, /* 16 bpp */
32*61046927SAndroid Build Coastguard Worker };
33*61046927SAndroid Build Coastguard Worker
34*61046927SAndroid Build Coastguard Worker static const VkExtent3D radv_sdma_t2t_alignment_3d[] = {
35*61046927SAndroid Build Coastguard Worker {8, 4, 8}, /* 1 bpp */
36*61046927SAndroid Build Coastguard Worker {4, 4, 8}, /* 2 bpp */
37*61046927SAndroid Build Coastguard Worker {4, 4, 4}, /* 4 bpp */
38*61046927SAndroid Build Coastguard Worker {4, 2, 4}, /* 8 bpp */
39*61046927SAndroid Build Coastguard Worker {2, 2, 4}, /* 16 bpp */
40*61046927SAndroid Build Coastguard Worker };
41*61046927SAndroid Build Coastguard Worker
42*61046927SAndroid Build Coastguard Worker ALWAYS_INLINE static unsigned
radv_sdma_pitch_alignment(const struct radv_device * device,const unsigned bpp)43*61046927SAndroid Build Coastguard Worker radv_sdma_pitch_alignment(const struct radv_device *device, const unsigned bpp)
44*61046927SAndroid Build Coastguard Worker {
45*61046927SAndroid Build Coastguard Worker const struct radv_physical_device *pdev = radv_device_physical(device);
46*61046927SAndroid Build Coastguard Worker
47*61046927SAndroid Build Coastguard Worker if (pdev->info.sdma_ip_version >= SDMA_5_0)
48*61046927SAndroid Build Coastguard Worker return MAX2(1, 4 / bpp);
49*61046927SAndroid Build Coastguard Worker
50*61046927SAndroid Build Coastguard Worker return 4;
51*61046927SAndroid Build Coastguard Worker }
52*61046927SAndroid Build Coastguard Worker
53*61046927SAndroid Build Coastguard Worker ALWAYS_INLINE static void
radv_sdma_check_pitches(const unsigned pitch,const unsigned slice_pitch,const unsigned bpp,const bool uses_depth)54*61046927SAndroid Build Coastguard Worker radv_sdma_check_pitches(const unsigned pitch, const unsigned slice_pitch, const unsigned bpp, const bool uses_depth)
55*61046927SAndroid Build Coastguard Worker {
56*61046927SAndroid Build Coastguard Worker ASSERTED const unsigned pitch_alignment = MAX2(1, 4 / bpp);
57*61046927SAndroid Build Coastguard Worker assert(pitch);
58*61046927SAndroid Build Coastguard Worker assert(pitch <= (1 << 14));
59*61046927SAndroid Build Coastguard Worker assert(util_is_aligned(pitch, pitch_alignment));
60*61046927SAndroid Build Coastguard Worker
61*61046927SAndroid Build Coastguard Worker if (uses_depth) {
62*61046927SAndroid Build Coastguard Worker ASSERTED const unsigned slice_pitch_alignment = 4;
63*61046927SAndroid Build Coastguard Worker assert(slice_pitch);
64*61046927SAndroid Build Coastguard Worker assert(slice_pitch <= (1 << 28));
65*61046927SAndroid Build Coastguard Worker assert(util_is_aligned(slice_pitch, slice_pitch_alignment));
66*61046927SAndroid Build Coastguard Worker }
67*61046927SAndroid Build Coastguard Worker }
68*61046927SAndroid Build Coastguard Worker
69*61046927SAndroid Build Coastguard Worker ALWAYS_INLINE static enum gfx9_resource_type
radv_sdma_surface_resource_type(const struct radv_device * const device,const struct radeon_surf * const surf)70*61046927SAndroid Build Coastguard Worker radv_sdma_surface_resource_type(const struct radv_device *const device, const struct radeon_surf *const surf)
71*61046927SAndroid Build Coastguard Worker {
72*61046927SAndroid Build Coastguard Worker const struct radv_physical_device *pdev = radv_device_physical(device);
73*61046927SAndroid Build Coastguard Worker
74*61046927SAndroid Build Coastguard Worker if (pdev->info.sdma_ip_version >= SDMA_5_0) {
75*61046927SAndroid Build Coastguard Worker /* Use the 2D resource type for rotated or Z swizzles. */
76*61046927SAndroid Build Coastguard Worker if ((surf->u.gfx9.resource_type == RADEON_RESOURCE_1D || surf->u.gfx9.resource_type == RADEON_RESOURCE_3D) &&
77*61046927SAndroid Build Coastguard Worker (surf->micro_tile_mode == RADEON_MICRO_MODE_RENDER || surf->micro_tile_mode == RADEON_MICRO_MODE_DEPTH))
78*61046927SAndroid Build Coastguard Worker return RADEON_RESOURCE_2D;
79*61046927SAndroid Build Coastguard Worker }
80*61046927SAndroid Build Coastguard Worker
81*61046927SAndroid Build Coastguard Worker return surf->u.gfx9.resource_type;
82*61046927SAndroid Build Coastguard Worker }
83*61046927SAndroid Build Coastguard Worker
84*61046927SAndroid Build Coastguard Worker ALWAYS_INLINE static uint32_t
radv_sdma_surface_type_from_aspect_mask(const VkImageAspectFlags aspectMask)85*61046927SAndroid Build Coastguard Worker radv_sdma_surface_type_from_aspect_mask(const VkImageAspectFlags aspectMask)
86*61046927SAndroid Build Coastguard Worker {
87*61046927SAndroid Build Coastguard Worker if (aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT)
88*61046927SAndroid Build Coastguard Worker return 1;
89*61046927SAndroid Build Coastguard Worker else if (aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT)
90*61046927SAndroid Build Coastguard Worker return 2;
91*61046927SAndroid Build Coastguard Worker
92*61046927SAndroid Build Coastguard Worker return 0;
93*61046927SAndroid Build Coastguard Worker }
94*61046927SAndroid Build Coastguard Worker
95*61046927SAndroid Build Coastguard Worker ALWAYS_INLINE static VkExtent3D
radv_sdma_pixel_extent_to_blocks(const VkExtent3D extent,const unsigned blk_w,const unsigned blk_h)96*61046927SAndroid Build Coastguard Worker radv_sdma_pixel_extent_to_blocks(const VkExtent3D extent, const unsigned blk_w, const unsigned blk_h)
97*61046927SAndroid Build Coastguard Worker {
98*61046927SAndroid Build Coastguard Worker const VkExtent3D r = {
99*61046927SAndroid Build Coastguard Worker .width = DIV_ROUND_UP(extent.width, blk_w),
100*61046927SAndroid Build Coastguard Worker .height = DIV_ROUND_UP(extent.height, blk_h),
101*61046927SAndroid Build Coastguard Worker .depth = extent.depth,
102*61046927SAndroid Build Coastguard Worker };
103*61046927SAndroid Build Coastguard Worker
104*61046927SAndroid Build Coastguard Worker return r;
105*61046927SAndroid Build Coastguard Worker }
106*61046927SAndroid Build Coastguard Worker
107*61046927SAndroid Build Coastguard Worker ALWAYS_INLINE static VkOffset3D
radv_sdma_pixel_offset_to_blocks(const VkOffset3D offset,const unsigned blk_w,const unsigned blk_h)108*61046927SAndroid Build Coastguard Worker radv_sdma_pixel_offset_to_blocks(const VkOffset3D offset, const unsigned blk_w, const unsigned blk_h)
109*61046927SAndroid Build Coastguard Worker {
110*61046927SAndroid Build Coastguard Worker const VkOffset3D r = {
111*61046927SAndroid Build Coastguard Worker .x = DIV_ROUND_UP(offset.x, blk_w),
112*61046927SAndroid Build Coastguard Worker .y = DIV_ROUND_UP(offset.y, blk_h),
113*61046927SAndroid Build Coastguard Worker .z = offset.z,
114*61046927SAndroid Build Coastguard Worker };
115*61046927SAndroid Build Coastguard Worker
116*61046927SAndroid Build Coastguard Worker return r;
117*61046927SAndroid Build Coastguard Worker }
118*61046927SAndroid Build Coastguard Worker
119*61046927SAndroid Build Coastguard Worker ALWAYS_INLINE static unsigned
radv_sdma_pixels_to_blocks(const unsigned linear_pitch,const unsigned blk_w)120*61046927SAndroid Build Coastguard Worker radv_sdma_pixels_to_blocks(const unsigned linear_pitch, const unsigned blk_w)
121*61046927SAndroid Build Coastguard Worker {
122*61046927SAndroid Build Coastguard Worker return DIV_ROUND_UP(linear_pitch, blk_w);
123*61046927SAndroid Build Coastguard Worker }
124*61046927SAndroid Build Coastguard Worker
125*61046927SAndroid Build Coastguard Worker ALWAYS_INLINE static unsigned
radv_sdma_pixel_area_to_blocks(const unsigned linear_slice_pitch,const unsigned blk_w,const unsigned blk_h)126*61046927SAndroid Build Coastguard Worker radv_sdma_pixel_area_to_blocks(const unsigned linear_slice_pitch, const unsigned blk_w, const unsigned blk_h)
127*61046927SAndroid Build Coastguard Worker {
128*61046927SAndroid Build Coastguard Worker return DIV_ROUND_UP(DIV_ROUND_UP(linear_slice_pitch, blk_w), blk_h);
129*61046927SAndroid Build Coastguard Worker }
130*61046927SAndroid Build Coastguard Worker
131*61046927SAndroid Build Coastguard Worker static struct radv_sdma_chunked_copy_info
radv_sdma_get_chunked_copy_info(const struct radv_device * const device,const struct radv_sdma_surf * const img,const VkExtent3D extent)132*61046927SAndroid Build Coastguard Worker radv_sdma_get_chunked_copy_info(const struct radv_device *const device, const struct radv_sdma_surf *const img,
133*61046927SAndroid Build Coastguard Worker const VkExtent3D extent)
134*61046927SAndroid Build Coastguard Worker {
135*61046927SAndroid Build Coastguard Worker const unsigned extent_horizontal_blocks = DIV_ROUND_UP(extent.width, img->blk_w);
136*61046927SAndroid Build Coastguard Worker const unsigned extent_vertical_blocks = DIV_ROUND_UP(extent.height, img->blk_h);
137*61046927SAndroid Build Coastguard Worker const unsigned aligned_row_pitch = ALIGN(extent_horizontal_blocks, 4);
138*61046927SAndroid Build Coastguard Worker const unsigned aligned_row_bytes = aligned_row_pitch * img->bpp;
139*61046927SAndroid Build Coastguard Worker
140*61046927SAndroid Build Coastguard Worker /* Assume that we can always copy at least one full row at a time. */
141*61046927SAndroid Build Coastguard Worker const unsigned max_num_rows_per_copy = MIN2(RADV_SDMA_TRANSFER_TEMP_BYTES / aligned_row_bytes, extent.height);
142*61046927SAndroid Build Coastguard Worker assert(max_num_rows_per_copy);
143*61046927SAndroid Build Coastguard Worker
144*61046927SAndroid Build Coastguard Worker /* Ensure that the number of rows copied at a time is a power of two. */
145*61046927SAndroid Build Coastguard Worker const unsigned num_rows_per_copy = MAX2(1, util_next_power_of_two(max_num_rows_per_copy + 1) / 2);
146*61046927SAndroid Build Coastguard Worker
147*61046927SAndroid Build Coastguard Worker const struct radv_sdma_chunked_copy_info r = {
148*61046927SAndroid Build Coastguard Worker .extent_horizontal_blocks = extent_horizontal_blocks,
149*61046927SAndroid Build Coastguard Worker .extent_vertical_blocks = extent_vertical_blocks,
150*61046927SAndroid Build Coastguard Worker .aligned_row_pitch = aligned_row_pitch,
151*61046927SAndroid Build Coastguard Worker .num_rows_per_copy = num_rows_per_copy,
152*61046927SAndroid Build Coastguard Worker };
153*61046927SAndroid Build Coastguard Worker
154*61046927SAndroid Build Coastguard Worker return r;
155*61046927SAndroid Build Coastguard Worker }
156*61046927SAndroid Build Coastguard Worker
157*61046927SAndroid Build Coastguard Worker struct radv_sdma_surf
radv_sdma_get_buf_surf(const struct radv_buffer * const buffer,const struct radv_image * const image,const VkBufferImageCopy2 * const region,const VkImageAspectFlags aspect_mask)158*61046927SAndroid Build Coastguard Worker radv_sdma_get_buf_surf(const struct radv_buffer *const buffer, const struct radv_image *const image,
159*61046927SAndroid Build Coastguard Worker const VkBufferImageCopy2 *const region, const VkImageAspectFlags aspect_mask)
160*61046927SAndroid Build Coastguard Worker {
161*61046927SAndroid Build Coastguard Worker assert(util_bitcount(aspect_mask) == 1);
162*61046927SAndroid Build Coastguard Worker
163*61046927SAndroid Build Coastguard Worker const unsigned pitch = (region->bufferRowLength ? region->bufferRowLength : region->imageExtent.width);
164*61046927SAndroid Build Coastguard Worker const unsigned slice_pitch =
165*61046927SAndroid Build Coastguard Worker (region->bufferImageHeight ? region->bufferImageHeight : region->imageExtent.height) * pitch;
166*61046927SAndroid Build Coastguard Worker
167*61046927SAndroid Build Coastguard Worker const unsigned plane_idx = radv_plane_from_aspect(region->imageSubresource.aspectMask);
168*61046927SAndroid Build Coastguard Worker const struct radeon_surf *surf = &image->planes[plane_idx].surface;
169*61046927SAndroid Build Coastguard Worker const struct radv_sdma_surf info = {
170*61046927SAndroid Build Coastguard Worker .va = radv_buffer_get_va(buffer->bo) + buffer->offset + region->bufferOffset,
171*61046927SAndroid Build Coastguard Worker .pitch = pitch,
172*61046927SAndroid Build Coastguard Worker .slice_pitch = slice_pitch,
173*61046927SAndroid Build Coastguard Worker .bpp = surf->bpe,
174*61046927SAndroid Build Coastguard Worker .blk_w = surf->blk_w,
175*61046927SAndroid Build Coastguard Worker .blk_h = surf->blk_h,
176*61046927SAndroid Build Coastguard Worker .is_linear = true,
177*61046927SAndroid Build Coastguard Worker };
178*61046927SAndroid Build Coastguard Worker
179*61046927SAndroid Build Coastguard Worker return info;
180*61046927SAndroid Build Coastguard Worker }
181*61046927SAndroid Build Coastguard Worker
182*61046927SAndroid Build Coastguard Worker static uint32_t
radv_sdma_get_metadata_config(const struct radv_device * const device,const struct radv_image * const image,const struct radeon_surf * const surf,const VkImageSubresourceLayers subresource,const VkImageAspectFlags aspect_mask)183*61046927SAndroid Build Coastguard Worker radv_sdma_get_metadata_config(const struct radv_device *const device, const struct radv_image *const image,
184*61046927SAndroid Build Coastguard Worker const struct radeon_surf *const surf, const VkImageSubresourceLayers subresource,
185*61046927SAndroid Build Coastguard Worker const VkImageAspectFlags aspect_mask)
186*61046927SAndroid Build Coastguard Worker {
187*61046927SAndroid Build Coastguard Worker const struct radv_physical_device *pdev = radv_device_physical(device);
188*61046927SAndroid Build Coastguard Worker
189*61046927SAndroid Build Coastguard Worker if (!pdev->info.sdma_supports_compression ||
190*61046927SAndroid Build Coastguard Worker !(radv_dcc_enabled(image, subresource.mipLevel) || radv_image_has_htile(image))) {
191*61046927SAndroid Build Coastguard Worker return 0;
192*61046927SAndroid Build Coastguard Worker }
193*61046927SAndroid Build Coastguard Worker
194*61046927SAndroid Build Coastguard Worker const VkFormat format = vk_format_get_aspect_format(image->vk.format, aspect_mask);
195*61046927SAndroid Build Coastguard Worker const struct util_format_description *desc = vk_format_description(format);
196*61046927SAndroid Build Coastguard Worker
197*61046927SAndroid Build Coastguard Worker const uint32_t data_format = ac_get_cb_format(pdev->info.gfx_level, vk_format_to_pipe_format(format));
198*61046927SAndroid Build Coastguard Worker const uint32_t alpha_is_on_msb = ac_alpha_is_on_msb(&pdev->info, vk_format_to_pipe_format(format));
199*61046927SAndroid Build Coastguard Worker const uint32_t number_type = radv_translate_buffer_numformat(desc, vk_format_get_first_non_void_channel(format));
200*61046927SAndroid Build Coastguard Worker const uint32_t surface_type = radv_sdma_surface_type_from_aspect_mask(aspect_mask);
201*61046927SAndroid Build Coastguard Worker const uint32_t max_comp_block_size = surf->u.gfx9.color.dcc.max_compressed_block_size;
202*61046927SAndroid Build Coastguard Worker const uint32_t max_uncomp_block_size = radv_get_dcc_max_uncompressed_block_size(device, image);
203*61046927SAndroid Build Coastguard Worker const uint32_t pipe_aligned = surf->u.gfx9.color.dcc.pipe_aligned;
204*61046927SAndroid Build Coastguard Worker
205*61046927SAndroid Build Coastguard Worker return data_format | alpha_is_on_msb << 8 | number_type << 9 | surface_type << 12 | max_comp_block_size << 24 |
206*61046927SAndroid Build Coastguard Worker max_uncomp_block_size << 26 | pipe_aligned << 31;
207*61046927SAndroid Build Coastguard Worker }
208*61046927SAndroid Build Coastguard Worker
209*61046927SAndroid Build Coastguard Worker static uint32_t
radv_sdma_get_tiled_info_dword(const struct radv_device * const device,const struct radv_image * const image,const struct radeon_surf * const surf,const VkImageSubresourceLayers subresource)210*61046927SAndroid Build Coastguard Worker radv_sdma_get_tiled_info_dword(const struct radv_device *const device, const struct radv_image *const image,
211*61046927SAndroid Build Coastguard Worker const struct radeon_surf *const surf, const VkImageSubresourceLayers subresource)
212*61046927SAndroid Build Coastguard Worker {
213*61046927SAndroid Build Coastguard Worker const struct radv_physical_device *pdev = radv_device_physical(device);
214*61046927SAndroid Build Coastguard Worker const uint32_t element_size = util_logbase2(surf->bpe);
215*61046927SAndroid Build Coastguard Worker const uint32_t swizzle_mode = surf->has_stencil ? surf->u.gfx9.zs.stencil_swizzle_mode : surf->u.gfx9.swizzle_mode;
216*61046927SAndroid Build Coastguard Worker uint32_t info = element_size | swizzle_mode << 3;
217*61046927SAndroid Build Coastguard Worker const enum sdma_version ver = pdev->info.sdma_ip_version;
218*61046927SAndroid Build Coastguard Worker
219*61046927SAndroid Build Coastguard Worker if (ver < SDMA_7_0) {
220*61046927SAndroid Build Coastguard Worker const enum gfx9_resource_type dimension = radv_sdma_surface_resource_type(device, surf);
221*61046927SAndroid Build Coastguard Worker info |= dimension << 9;
222*61046927SAndroid Build Coastguard Worker }
223*61046927SAndroid Build Coastguard Worker
224*61046927SAndroid Build Coastguard Worker if (ver >= SDMA_5_0) {
225*61046927SAndroid Build Coastguard Worker const uint32_t mip_max = MAX2(image->vk.mip_levels, 1);
226*61046927SAndroid Build Coastguard Worker const uint32_t mip_id = subresource.mipLevel;
227*61046927SAndroid Build Coastguard Worker
228*61046927SAndroid Build Coastguard Worker return info | (mip_max - 1) << 16 | mip_id << 20;
229*61046927SAndroid Build Coastguard Worker } else if (ver >= SDMA_4_0) {
230*61046927SAndroid Build Coastguard Worker return info | surf->u.gfx9.epitch << 16;
231*61046927SAndroid Build Coastguard Worker } else {
232*61046927SAndroid Build Coastguard Worker unreachable("unsupported SDMA version");
233*61046927SAndroid Build Coastguard Worker }
234*61046927SAndroid Build Coastguard Worker }
235*61046927SAndroid Build Coastguard Worker
236*61046927SAndroid Build Coastguard Worker static uint32_t
radv_sdma_get_tiled_header_dword(const struct radv_device * const device,const struct radv_image * const image,const VkImageSubresourceLayers subresource)237*61046927SAndroid Build Coastguard Worker radv_sdma_get_tiled_header_dword(const struct radv_device *const device, const struct radv_image *const image,
238*61046927SAndroid Build Coastguard Worker const VkImageSubresourceLayers subresource)
239*61046927SAndroid Build Coastguard Worker {
240*61046927SAndroid Build Coastguard Worker const struct radv_physical_device *pdev = radv_device_physical(device);
241*61046927SAndroid Build Coastguard Worker const enum sdma_version ver = pdev->info.sdma_ip_version;
242*61046927SAndroid Build Coastguard Worker
243*61046927SAndroid Build Coastguard Worker if (ver >= SDMA_5_0) {
244*61046927SAndroid Build Coastguard Worker return 0;
245*61046927SAndroid Build Coastguard Worker } else if (ver >= SDMA_4_0) {
246*61046927SAndroid Build Coastguard Worker const uint32_t mip_max = MAX2(image->vk.mip_levels, 1);
247*61046927SAndroid Build Coastguard Worker const uint32_t mip_id = subresource.mipLevel;
248*61046927SAndroid Build Coastguard Worker return (mip_max - 1) << 20 | mip_id << 24;
249*61046927SAndroid Build Coastguard Worker } else {
250*61046927SAndroid Build Coastguard Worker unreachable("unsupported SDMA version");
251*61046927SAndroid Build Coastguard Worker }
252*61046927SAndroid Build Coastguard Worker }
253*61046927SAndroid Build Coastguard Worker
254*61046927SAndroid Build Coastguard Worker struct radv_sdma_surf
radv_sdma_get_surf(const struct radv_device * const device,const struct radv_image * const image,const VkImageSubresourceLayers subresource,const VkOffset3D offset,const VkImageAspectFlags aspect_mask)255*61046927SAndroid Build Coastguard Worker radv_sdma_get_surf(const struct radv_device *const device, const struct radv_image *const image,
256*61046927SAndroid Build Coastguard Worker const VkImageSubresourceLayers subresource, const VkOffset3D offset,
257*61046927SAndroid Build Coastguard Worker const VkImageAspectFlags aspect_mask)
258*61046927SAndroid Build Coastguard Worker {
259*61046927SAndroid Build Coastguard Worker assert(util_bitcount(aspect_mask) == 1);
260*61046927SAndroid Build Coastguard Worker
261*61046927SAndroid Build Coastguard Worker const struct radv_physical_device *pdev = radv_device_physical(device);
262*61046927SAndroid Build Coastguard Worker const unsigned plane_idx = radv_plane_from_aspect(aspect_mask);
263*61046927SAndroid Build Coastguard Worker const unsigned binding_idx = image->disjoint ? plane_idx : 0;
264*61046927SAndroid Build Coastguard Worker const struct radeon_surf *const surf = &image->planes[plane_idx].surface;
265*61046927SAndroid Build Coastguard Worker const uint64_t va = radv_image_get_va(image, binding_idx);
266*61046927SAndroid Build Coastguard Worker struct radv_sdma_surf info = {
267*61046927SAndroid Build Coastguard Worker .extent =
268*61046927SAndroid Build Coastguard Worker {
269*61046927SAndroid Build Coastguard Worker .width = vk_format_get_plane_width(image->vk.format, plane_idx, image->vk.extent.width),
270*61046927SAndroid Build Coastguard Worker .height = vk_format_get_plane_height(image->vk.format, plane_idx, image->vk.extent.height),
271*61046927SAndroid Build Coastguard Worker .depth = image->vk.image_type == VK_IMAGE_TYPE_3D ? image->vk.extent.depth : image->vk.array_layers,
272*61046927SAndroid Build Coastguard Worker },
273*61046927SAndroid Build Coastguard Worker .offset =
274*61046927SAndroid Build Coastguard Worker {
275*61046927SAndroid Build Coastguard Worker .x = offset.x,
276*61046927SAndroid Build Coastguard Worker .y = offset.y,
277*61046927SAndroid Build Coastguard Worker .z = image->vk.image_type == VK_IMAGE_TYPE_3D ? offset.z : subresource.baseArrayLayer,
278*61046927SAndroid Build Coastguard Worker },
279*61046927SAndroid Build Coastguard Worker .bpp = surf->bpe,
280*61046927SAndroid Build Coastguard Worker .blk_w = surf->blk_w,
281*61046927SAndroid Build Coastguard Worker .blk_h = surf->blk_h,
282*61046927SAndroid Build Coastguard Worker .mip_levels = image->vk.mip_levels,
283*61046927SAndroid Build Coastguard Worker .micro_tile_mode = surf->micro_tile_mode,
284*61046927SAndroid Build Coastguard Worker .is_linear = surf->is_linear,
285*61046927SAndroid Build Coastguard Worker .is_3d = surf->u.gfx9.resource_type == RADEON_RESOURCE_3D,
286*61046927SAndroid Build Coastguard Worker };
287*61046927SAndroid Build Coastguard Worker
288*61046927SAndroid Build Coastguard Worker if (surf->is_linear) {
289*61046927SAndroid Build Coastguard Worker info.va = va + surf->u.gfx9.surf_offset + surf->u.gfx9.offset[subresource.mipLevel];
290*61046927SAndroid Build Coastguard Worker info.pitch = surf->u.gfx9.pitch[subresource.mipLevel];
291*61046927SAndroid Build Coastguard Worker info.slice_pitch = surf->blk_w * surf->blk_h * surf->u.gfx9.surf_slice_size / surf->bpe;
292*61046927SAndroid Build Coastguard Worker } else {
293*61046927SAndroid Build Coastguard Worker /* 1D resources should be linear. */
294*61046927SAndroid Build Coastguard Worker assert(surf->u.gfx9.resource_type != RADEON_RESOURCE_1D);
295*61046927SAndroid Build Coastguard Worker
296*61046927SAndroid Build Coastguard Worker info.va = (va + surf->u.gfx9.surf_offset) | surf->tile_swizzle << 8;
297*61046927SAndroid Build Coastguard Worker info.info_dword = radv_sdma_get_tiled_info_dword(device, image, surf, subresource);
298*61046927SAndroid Build Coastguard Worker info.header_dword = radv_sdma_get_tiled_header_dword(device, image, subresource);
299*61046927SAndroid Build Coastguard Worker
300*61046927SAndroid Build Coastguard Worker if (pdev->info.sdma_supports_compression &&
301*61046927SAndroid Build Coastguard Worker (radv_dcc_enabled(image, subresource.mipLevel) || radv_image_has_htile(image))) {
302*61046927SAndroid Build Coastguard Worker info.meta_va = va + surf->meta_offset;
303*61046927SAndroid Build Coastguard Worker info.meta_config = radv_sdma_get_metadata_config(device, image, surf, subresource, aspect_mask);
304*61046927SAndroid Build Coastguard Worker }
305*61046927SAndroid Build Coastguard Worker }
306*61046927SAndroid Build Coastguard Worker
307*61046927SAndroid Build Coastguard Worker return info;
308*61046927SAndroid Build Coastguard Worker }
309*61046927SAndroid Build Coastguard Worker
310*61046927SAndroid Build Coastguard Worker static void
radv_sdma_emit_nop(const struct radv_device * device,struct radeon_cmdbuf * cs)311*61046927SAndroid Build Coastguard Worker radv_sdma_emit_nop(const struct radv_device *device, struct radeon_cmdbuf *cs)
312*61046927SAndroid Build Coastguard Worker {
313*61046927SAndroid Build Coastguard Worker /* SDMA NOP acts as a fence command and causes the SDMA engine to wait for pending copy operations. */
314*61046927SAndroid Build Coastguard Worker radeon_check_space(device->ws, cs, 1);
315*61046927SAndroid Build Coastguard Worker radeon_emit(cs, SDMA_PACKET(SDMA_OPCODE_NOP, 0, 0));
316*61046927SAndroid Build Coastguard Worker }
317*61046927SAndroid Build Coastguard Worker
318*61046927SAndroid Build Coastguard Worker void
radv_sdma_copy_buffer(const struct radv_device * device,struct radeon_cmdbuf * cs,uint64_t src_va,uint64_t dst_va,uint64_t size)319*61046927SAndroid Build Coastguard Worker radv_sdma_copy_buffer(const struct radv_device *device, struct radeon_cmdbuf *cs, uint64_t src_va, uint64_t dst_va,
320*61046927SAndroid Build Coastguard Worker uint64_t size)
321*61046927SAndroid Build Coastguard Worker {
322*61046927SAndroid Build Coastguard Worker if (size == 0)
323*61046927SAndroid Build Coastguard Worker return;
324*61046927SAndroid Build Coastguard Worker
325*61046927SAndroid Build Coastguard Worker const struct radv_physical_device *pdev = radv_device_physical(device);
326*61046927SAndroid Build Coastguard Worker const enum sdma_version ver = pdev->info.sdma_ip_version;
327*61046927SAndroid Build Coastguard Worker const unsigned max_size_per_packet = ver >= SDMA_5_2 ? SDMA_V5_2_COPY_MAX_BYTES : SDMA_V2_0_COPY_MAX_BYTES;
328*61046927SAndroid Build Coastguard Worker
329*61046927SAndroid Build Coastguard Worker unsigned align = ~0u;
330*61046927SAndroid Build Coastguard Worker unsigned ncopy = DIV_ROUND_UP(size, max_size_per_packet);
331*61046927SAndroid Build Coastguard Worker
332*61046927SAndroid Build Coastguard Worker assert(ver >= SDMA_2_0);
333*61046927SAndroid Build Coastguard Worker
334*61046927SAndroid Build Coastguard Worker /* SDMA FW automatically enables a faster dword copy mode when
335*61046927SAndroid Build Coastguard Worker * source, destination and size are all dword-aligned.
336*61046927SAndroid Build Coastguard Worker *
337*61046927SAndroid Build Coastguard Worker * When source and destination are dword-aligned, round down the size to
338*61046927SAndroid Build Coastguard Worker * take advantage of faster dword copy, and copy the remaining few bytes
339*61046927SAndroid Build Coastguard Worker * with the last copy packet.
340*61046927SAndroid Build Coastguard Worker */
341*61046927SAndroid Build Coastguard Worker if ((src_va & 0x3) == 0 && (dst_va & 0x3) == 0 && size > 4 && (size & 0x3) != 0) {
342*61046927SAndroid Build Coastguard Worker align = ~0x3u;
343*61046927SAndroid Build Coastguard Worker ncopy++;
344*61046927SAndroid Build Coastguard Worker }
345*61046927SAndroid Build Coastguard Worker
346*61046927SAndroid Build Coastguard Worker radeon_check_space(device->ws, cs, ncopy * 7);
347*61046927SAndroid Build Coastguard Worker
348*61046927SAndroid Build Coastguard Worker for (unsigned i = 0; i < ncopy; i++) {
349*61046927SAndroid Build Coastguard Worker unsigned csize = size >= 4 ? MIN2(size & align, max_size_per_packet) : size;
350*61046927SAndroid Build Coastguard Worker radeon_emit(cs, SDMA_PACKET(SDMA_OPCODE_COPY, SDMA_COPY_SUB_OPCODE_LINEAR, 0));
351*61046927SAndroid Build Coastguard Worker radeon_emit(cs, ver >= SDMA_4_0 ? csize - 1 : csize);
352*61046927SAndroid Build Coastguard Worker radeon_emit(cs, 0); /* src/dst endian swap */
353*61046927SAndroid Build Coastguard Worker radeon_emit(cs, src_va);
354*61046927SAndroid Build Coastguard Worker radeon_emit(cs, src_va >> 32);
355*61046927SAndroid Build Coastguard Worker radeon_emit(cs, dst_va);
356*61046927SAndroid Build Coastguard Worker radeon_emit(cs, dst_va >> 32);
357*61046927SAndroid Build Coastguard Worker dst_va += csize;
358*61046927SAndroid Build Coastguard Worker src_va += csize;
359*61046927SAndroid Build Coastguard Worker size -= csize;
360*61046927SAndroid Build Coastguard Worker }
361*61046927SAndroid Build Coastguard Worker }
362*61046927SAndroid Build Coastguard Worker
363*61046927SAndroid Build Coastguard Worker void
radv_sdma_fill_buffer(const struct radv_device * device,struct radeon_cmdbuf * cs,const uint64_t va,const uint64_t size,const uint32_t value)364*61046927SAndroid Build Coastguard Worker radv_sdma_fill_buffer(const struct radv_device *device, struct radeon_cmdbuf *cs, const uint64_t va,
365*61046927SAndroid Build Coastguard Worker const uint64_t size, const uint32_t value)
366*61046927SAndroid Build Coastguard Worker {
367*61046927SAndroid Build Coastguard Worker const struct radv_physical_device *pdev = radv_device_physical(device);
368*61046927SAndroid Build Coastguard Worker
369*61046927SAndroid Build Coastguard Worker const uint32_t fill_size = 2; /* This means that the count is in dwords. */
370*61046927SAndroid Build Coastguard Worker const uint32_t constant_fill_header = SDMA_PACKET(SDMA_OPCODE_CONSTANT_FILL, 0, 0) | (fill_size & 0x3) << 30;
371*61046927SAndroid Build Coastguard Worker
372*61046927SAndroid Build Coastguard Worker /* This packet is the same since SDMA v2.4, haven't bothered to check older versions. */
373*61046927SAndroid Build Coastguard Worker const enum sdma_version ver = pdev->info.sdma_ip_version;
374*61046927SAndroid Build Coastguard Worker assert(ver >= SDMA_2_4);
375*61046927SAndroid Build Coastguard Worker
376*61046927SAndroid Build Coastguard Worker /* Maximum allowed fill size depends on the GPU.
377*61046927SAndroid Build Coastguard Worker * Emit as many packets as necessary to fill all the bytes we need.
378*61046927SAndroid Build Coastguard Worker */
379*61046927SAndroid Build Coastguard Worker const uint64_t max_fill_bytes = BITFIELD64_MASK(ver >= SDMA_6_0 ? 30 : 22) & ~0x3;
380*61046927SAndroid Build Coastguard Worker const unsigned num_packets = DIV_ROUND_UP(size, max_fill_bytes);
381*61046927SAndroid Build Coastguard Worker ASSERTED unsigned cdw_max = radeon_check_space(device->ws, cs, num_packets * 5);
382*61046927SAndroid Build Coastguard Worker
383*61046927SAndroid Build Coastguard Worker for (unsigned i = 0; i < num_packets; ++i) {
384*61046927SAndroid Build Coastguard Worker const uint64_t offset = i * max_fill_bytes;
385*61046927SAndroid Build Coastguard Worker const uint64_t fill_bytes = MIN2(size - offset, max_fill_bytes);
386*61046927SAndroid Build Coastguard Worker const uint64_t fill_va = va + offset;
387*61046927SAndroid Build Coastguard Worker
388*61046927SAndroid Build Coastguard Worker radeon_emit(cs, constant_fill_header);
389*61046927SAndroid Build Coastguard Worker radeon_emit(cs, fill_va);
390*61046927SAndroid Build Coastguard Worker radeon_emit(cs, fill_va >> 32);
391*61046927SAndroid Build Coastguard Worker radeon_emit(cs, value);
392*61046927SAndroid Build Coastguard Worker radeon_emit(cs, fill_bytes - 1); /* Must be programmed in bytes, even if the fill is done in dwords. */
393*61046927SAndroid Build Coastguard Worker }
394*61046927SAndroid Build Coastguard Worker
395*61046927SAndroid Build Coastguard Worker assert(cs->cdw <= cdw_max);
396*61046927SAndroid Build Coastguard Worker }
397*61046927SAndroid Build Coastguard Worker
398*61046927SAndroid Build Coastguard Worker static void
radv_sdma_emit_copy_linear_sub_window(const struct radv_device * device,struct radeon_cmdbuf * cs,const struct radv_sdma_surf * const src,const struct radv_sdma_surf * const dst,const VkExtent3D pix_extent)399*61046927SAndroid Build Coastguard Worker radv_sdma_emit_copy_linear_sub_window(const struct radv_device *device, struct radeon_cmdbuf *cs,
400*61046927SAndroid Build Coastguard Worker const struct radv_sdma_surf *const src, const struct radv_sdma_surf *const dst,
401*61046927SAndroid Build Coastguard Worker const VkExtent3D pix_extent)
402*61046927SAndroid Build Coastguard Worker {
403*61046927SAndroid Build Coastguard Worker /* This packet is the same since SDMA v2.4, haven't bothered to check older versions.
404*61046927SAndroid Build Coastguard Worker * The main difference is the bitfield sizes:
405*61046927SAndroid Build Coastguard Worker *
406*61046927SAndroid Build Coastguard Worker * v2.4 - src/dst_pitch: 14 bits, rect_z: 11 bits
407*61046927SAndroid Build Coastguard Worker * v4.0 - src/dst_pitch: 19 bits, rect_z: 11 bits
408*61046927SAndroid Build Coastguard Worker * v5.0 - src/dst_pitch: 19 bits, rect_z: 13 bits
409*61046927SAndroid Build Coastguard Worker *
410*61046927SAndroid Build Coastguard Worker * We currently use the smallest limits (from SDMA v2.4).
411*61046927SAndroid Build Coastguard Worker */
412*61046927SAndroid Build Coastguard Worker
413*61046927SAndroid Build Coastguard Worker const VkOffset3D src_off = radv_sdma_pixel_offset_to_blocks(src->offset, src->blk_w, src->blk_h);
414*61046927SAndroid Build Coastguard Worker const VkOffset3D dst_off = radv_sdma_pixel_offset_to_blocks(dst->offset, dst->blk_w, dst->blk_h);
415*61046927SAndroid Build Coastguard Worker const VkExtent3D ext = radv_sdma_pixel_extent_to_blocks(pix_extent, src->blk_w, src->blk_h);
416*61046927SAndroid Build Coastguard Worker const unsigned src_pitch = radv_sdma_pixels_to_blocks(src->pitch, src->blk_w);
417*61046927SAndroid Build Coastguard Worker const unsigned dst_pitch = radv_sdma_pixels_to_blocks(dst->pitch, dst->blk_w);
418*61046927SAndroid Build Coastguard Worker const unsigned src_slice_pitch = radv_sdma_pixel_area_to_blocks(src->slice_pitch, src->blk_w, src->blk_h);
419*61046927SAndroid Build Coastguard Worker const unsigned dst_slice_pitch = radv_sdma_pixel_area_to_blocks(dst->slice_pitch, dst->blk_w, dst->blk_h);
420*61046927SAndroid Build Coastguard Worker
421*61046927SAndroid Build Coastguard Worker assert(src->bpp == dst->bpp);
422*61046927SAndroid Build Coastguard Worker assert(util_is_power_of_two_nonzero(src->bpp));
423*61046927SAndroid Build Coastguard Worker radv_sdma_check_pitches(src->pitch, src->slice_pitch, src->bpp, false);
424*61046927SAndroid Build Coastguard Worker radv_sdma_check_pitches(dst->pitch, dst->slice_pitch, dst->bpp, false);
425*61046927SAndroid Build Coastguard Worker
426*61046927SAndroid Build Coastguard Worker ASSERTED unsigned cdw_end = radeon_check_space(device->ws, cs, 13);
427*61046927SAndroid Build Coastguard Worker
428*61046927SAndroid Build Coastguard Worker radeon_emit(cs, SDMA_PACKET(SDMA_OPCODE_COPY, SDMA_COPY_SUB_OPCODE_LINEAR_SUB_WINDOW, 0) | util_logbase2(src->bpp)
429*61046927SAndroid Build Coastguard Worker << 29);
430*61046927SAndroid Build Coastguard Worker radeon_emit(cs, src->va);
431*61046927SAndroid Build Coastguard Worker radeon_emit(cs, src->va >> 32);
432*61046927SAndroid Build Coastguard Worker radeon_emit(cs, src_off.x | src_off.y << 16);
433*61046927SAndroid Build Coastguard Worker radeon_emit(cs, src_off.z | (src_pitch - 1) << 13);
434*61046927SAndroid Build Coastguard Worker radeon_emit(cs, src_slice_pitch - 1);
435*61046927SAndroid Build Coastguard Worker radeon_emit(cs, dst->va);
436*61046927SAndroid Build Coastguard Worker radeon_emit(cs, dst->va >> 32);
437*61046927SAndroid Build Coastguard Worker radeon_emit(cs, dst_off.x | dst_off.y << 16);
438*61046927SAndroid Build Coastguard Worker radeon_emit(cs, dst_off.z | (dst_pitch - 1) << 13);
439*61046927SAndroid Build Coastguard Worker radeon_emit(cs, dst_slice_pitch - 1);
440*61046927SAndroid Build Coastguard Worker radeon_emit(cs, (ext.width - 1) | (ext.height - 1) << 16);
441*61046927SAndroid Build Coastguard Worker radeon_emit(cs, (ext.depth - 1));
442*61046927SAndroid Build Coastguard Worker
443*61046927SAndroid Build Coastguard Worker assert(cs->cdw == cdw_end);
444*61046927SAndroid Build Coastguard Worker }
445*61046927SAndroid Build Coastguard Worker
446*61046927SAndroid Build Coastguard Worker static void
radv_sdma_emit_copy_tiled_sub_window(const struct radv_device * device,struct radeon_cmdbuf * cs,const struct radv_sdma_surf * const tiled,const struct radv_sdma_surf * const linear,const VkExtent3D pix_extent,const bool detile)447*61046927SAndroid Build Coastguard Worker radv_sdma_emit_copy_tiled_sub_window(const struct radv_device *device, struct radeon_cmdbuf *cs,
448*61046927SAndroid Build Coastguard Worker const struct radv_sdma_surf *const tiled,
449*61046927SAndroid Build Coastguard Worker const struct radv_sdma_surf *const linear, const VkExtent3D pix_extent,
450*61046927SAndroid Build Coastguard Worker const bool detile)
451*61046927SAndroid Build Coastguard Worker {
452*61046927SAndroid Build Coastguard Worker const struct radv_physical_device *pdev = radv_device_physical(device);
453*61046927SAndroid Build Coastguard Worker
454*61046927SAndroid Build Coastguard Worker if (!pdev->info.sdma_supports_compression) {
455*61046927SAndroid Build Coastguard Worker assert(!tiled->meta_va);
456*61046927SAndroid Build Coastguard Worker }
457*61046927SAndroid Build Coastguard Worker
458*61046927SAndroid Build Coastguard Worker const VkOffset3D linear_off = radv_sdma_pixel_offset_to_blocks(linear->offset, linear->blk_w, linear->blk_h);
459*61046927SAndroid Build Coastguard Worker const VkOffset3D tiled_off = radv_sdma_pixel_offset_to_blocks(tiled->offset, tiled->blk_w, tiled->blk_h);
460*61046927SAndroid Build Coastguard Worker const VkExtent3D tiled_ext = radv_sdma_pixel_extent_to_blocks(tiled->extent, tiled->blk_w, tiled->blk_h);
461*61046927SAndroid Build Coastguard Worker const VkExtent3D ext = radv_sdma_pixel_extent_to_blocks(pix_extent, tiled->blk_w, tiled->blk_h);
462*61046927SAndroid Build Coastguard Worker const unsigned linear_pitch = radv_sdma_pixels_to_blocks(linear->pitch, tiled->blk_w);
463*61046927SAndroid Build Coastguard Worker const unsigned linear_slice_pitch = radv_sdma_pixel_area_to_blocks(linear->slice_pitch, tiled->blk_w, tiled->blk_h);
464*61046927SAndroid Build Coastguard Worker const bool dcc = !!tiled->meta_va;
465*61046927SAndroid Build Coastguard Worker const bool uses_depth = linear_off.z != 0 || tiled_off.z != 0 || ext.depth != 1;
466*61046927SAndroid Build Coastguard Worker
467*61046927SAndroid Build Coastguard Worker assert(util_is_power_of_two_nonzero(tiled->bpp));
468*61046927SAndroid Build Coastguard Worker radv_sdma_check_pitches(linear_pitch, linear_slice_pitch, tiled->bpp, uses_depth);
469*61046927SAndroid Build Coastguard Worker
470*61046927SAndroid Build Coastguard Worker ASSERTED unsigned cdw_end = radeon_check_space(device->ws, cs, 14 + (dcc ? 3 : 0));
471*61046927SAndroid Build Coastguard Worker
472*61046927SAndroid Build Coastguard Worker radeon_emit(cs, SDMA_PACKET(SDMA_OPCODE_COPY, SDMA_COPY_SUB_OPCODE_TILED_SUB_WINDOW, 0) | dcc << 19 | detile << 31 |
473*61046927SAndroid Build Coastguard Worker tiled->header_dword);
474*61046927SAndroid Build Coastguard Worker radeon_emit(cs, tiled->va);
475*61046927SAndroid Build Coastguard Worker radeon_emit(cs, tiled->va >> 32);
476*61046927SAndroid Build Coastguard Worker radeon_emit(cs, tiled_off.x | tiled_off.y << 16);
477*61046927SAndroid Build Coastguard Worker radeon_emit(cs, tiled_off.z | (tiled_ext.width - 1) << 16);
478*61046927SAndroid Build Coastguard Worker radeon_emit(cs, (tiled_ext.height - 1) | (tiled_ext.depth - 1) << 16);
479*61046927SAndroid Build Coastguard Worker radeon_emit(cs, tiled->info_dword);
480*61046927SAndroid Build Coastguard Worker radeon_emit(cs, linear->va);
481*61046927SAndroid Build Coastguard Worker radeon_emit(cs, linear->va >> 32);
482*61046927SAndroid Build Coastguard Worker radeon_emit(cs, linear_off.x | linear_off.y << 16);
483*61046927SAndroid Build Coastguard Worker radeon_emit(cs, linear_off.z | (linear_pitch - 1) << 16);
484*61046927SAndroid Build Coastguard Worker radeon_emit(cs, linear_slice_pitch - 1);
485*61046927SAndroid Build Coastguard Worker radeon_emit(cs, (ext.width - 1) | (ext.height - 1) << 16);
486*61046927SAndroid Build Coastguard Worker radeon_emit(cs, (ext.depth - 1));
487*61046927SAndroid Build Coastguard Worker
488*61046927SAndroid Build Coastguard Worker if (tiled->meta_va) {
489*61046927SAndroid Build Coastguard Worker const unsigned write_compress_enable = !detile;
490*61046927SAndroid Build Coastguard Worker radeon_emit(cs, tiled->meta_va);
491*61046927SAndroid Build Coastguard Worker radeon_emit(cs, tiled->meta_va >> 32);
492*61046927SAndroid Build Coastguard Worker radeon_emit(cs, tiled->meta_config | write_compress_enable << 28);
493*61046927SAndroid Build Coastguard Worker }
494*61046927SAndroid Build Coastguard Worker
495*61046927SAndroid Build Coastguard Worker assert(cs->cdw == cdw_end);
496*61046927SAndroid Build Coastguard Worker }
497*61046927SAndroid Build Coastguard Worker
498*61046927SAndroid Build Coastguard Worker static void
radv_sdma_emit_copy_t2t_sub_window(const struct radv_device * device,struct radeon_cmdbuf * cs,const struct radv_sdma_surf * const src,const struct radv_sdma_surf * const dst,const VkExtent3D px_extent)499*61046927SAndroid Build Coastguard Worker radv_sdma_emit_copy_t2t_sub_window(const struct radv_device *device, struct radeon_cmdbuf *cs,
500*61046927SAndroid Build Coastguard Worker const struct radv_sdma_surf *const src, const struct radv_sdma_surf *const dst,
501*61046927SAndroid Build Coastguard Worker const VkExtent3D px_extent)
502*61046927SAndroid Build Coastguard Worker {
503*61046927SAndroid Build Coastguard Worker const struct radv_physical_device *pdev = radv_device_physical(device);
504*61046927SAndroid Build Coastguard Worker
505*61046927SAndroid Build Coastguard Worker /* We currently only support the SDMA v4+ versions of this packet. */
506*61046927SAndroid Build Coastguard Worker assert(pdev->info.sdma_ip_version >= SDMA_4_0);
507*61046927SAndroid Build Coastguard Worker
508*61046927SAndroid Build Coastguard Worker /* On GFX10+ this supports DCC, but cannot copy a compressed surface to another compressed surface. */
509*61046927SAndroid Build Coastguard Worker assert(!src->meta_va || !dst->meta_va);
510*61046927SAndroid Build Coastguard Worker
511*61046927SAndroid Build Coastguard Worker if (pdev->info.sdma_ip_version >= SDMA_4_0 && pdev->info.sdma_ip_version < SDMA_5_0) {
512*61046927SAndroid Build Coastguard Worker /* SDMA v4 doesn't support mip_id selection in the T2T copy packet. */
513*61046927SAndroid Build Coastguard Worker assert(src->header_dword >> 24 == 0);
514*61046927SAndroid Build Coastguard Worker assert(dst->header_dword >> 24 == 0);
515*61046927SAndroid Build Coastguard Worker /* SDMA v4 doesn't support any image metadata. */
516*61046927SAndroid Build Coastguard Worker assert(!src->meta_va);
517*61046927SAndroid Build Coastguard Worker assert(!dst->meta_va);
518*61046927SAndroid Build Coastguard Worker }
519*61046927SAndroid Build Coastguard Worker
520*61046927SAndroid Build Coastguard Worker /* Despite the name, this can indicate DCC or HTILE metadata. */
521*61046927SAndroid Build Coastguard Worker const uint32_t dcc = src->meta_va || dst->meta_va;
522*61046927SAndroid Build Coastguard Worker /* 0 = compress (src is uncompressed), 1 = decompress (src is compressed). */
523*61046927SAndroid Build Coastguard Worker const uint32_t dcc_dir = src->meta_va && !dst->meta_va;
524*61046927SAndroid Build Coastguard Worker
525*61046927SAndroid Build Coastguard Worker const VkOffset3D src_off = radv_sdma_pixel_offset_to_blocks(src->offset, src->blk_w, src->blk_h);
526*61046927SAndroid Build Coastguard Worker const VkOffset3D dst_off = radv_sdma_pixel_offset_to_blocks(dst->offset, dst->blk_w, dst->blk_h);
527*61046927SAndroid Build Coastguard Worker const VkExtent3D src_ext = radv_sdma_pixel_extent_to_blocks(src->extent, src->blk_w, src->blk_h);
528*61046927SAndroid Build Coastguard Worker const VkExtent3D dst_ext = radv_sdma_pixel_extent_to_blocks(dst->extent, dst->blk_w, dst->blk_h);
529*61046927SAndroid Build Coastguard Worker const VkExtent3D ext = radv_sdma_pixel_extent_to_blocks(px_extent, src->blk_w, src->blk_h);
530*61046927SAndroid Build Coastguard Worker
531*61046927SAndroid Build Coastguard Worker assert(util_is_power_of_two_nonzero(src->bpp));
532*61046927SAndroid Build Coastguard Worker assert(util_is_power_of_two_nonzero(dst->bpp));
533*61046927SAndroid Build Coastguard Worker
534*61046927SAndroid Build Coastguard Worker ASSERTED unsigned cdw_end = radeon_check_space(device->ws, cs, 15 + (dcc ? 3 : 0));
535*61046927SAndroid Build Coastguard Worker
536*61046927SAndroid Build Coastguard Worker radeon_emit(cs, SDMA_PACKET(SDMA_OPCODE_COPY, SDMA_COPY_SUB_OPCODE_T2T_SUB_WINDOW, 0) | dcc << 19 | dcc_dir << 31 |
537*61046927SAndroid Build Coastguard Worker src->header_dword);
538*61046927SAndroid Build Coastguard Worker radeon_emit(cs, src->va);
539*61046927SAndroid Build Coastguard Worker radeon_emit(cs, src->va >> 32);
540*61046927SAndroid Build Coastguard Worker radeon_emit(cs, src_off.x | src_off.y << 16);
541*61046927SAndroid Build Coastguard Worker radeon_emit(cs, src_off.z | (src_ext.width - 1) << 16);
542*61046927SAndroid Build Coastguard Worker radeon_emit(cs, (src_ext.height - 1) | (src_ext.depth - 1) << 16);
543*61046927SAndroid Build Coastguard Worker radeon_emit(cs, src->info_dword);
544*61046927SAndroid Build Coastguard Worker radeon_emit(cs, dst->va);
545*61046927SAndroid Build Coastguard Worker radeon_emit(cs, dst->va >> 32);
546*61046927SAndroid Build Coastguard Worker radeon_emit(cs, dst_off.x | dst_off.y << 16);
547*61046927SAndroid Build Coastguard Worker radeon_emit(cs, dst_off.z | (dst_ext.width - 1) << 16);
548*61046927SAndroid Build Coastguard Worker radeon_emit(cs, (dst_ext.height - 1) | (dst_ext.depth - 1) << 16);
549*61046927SAndroid Build Coastguard Worker radeon_emit(cs, dst->info_dword);
550*61046927SAndroid Build Coastguard Worker radeon_emit(cs, (ext.width - 1) | (ext.height - 1) << 16);
551*61046927SAndroid Build Coastguard Worker radeon_emit(cs, (ext.depth - 1));
552*61046927SAndroid Build Coastguard Worker
553*61046927SAndroid Build Coastguard Worker if (dst->meta_va) {
554*61046927SAndroid Build Coastguard Worker const uint32_t write_compress_enable = 1;
555*61046927SAndroid Build Coastguard Worker radeon_emit(cs, dst->meta_va);
556*61046927SAndroid Build Coastguard Worker radeon_emit(cs, dst->meta_va >> 32);
557*61046927SAndroid Build Coastguard Worker radeon_emit(cs, dst->meta_config | write_compress_enable << 28);
558*61046927SAndroid Build Coastguard Worker } else if (src->meta_va) {
559*61046927SAndroid Build Coastguard Worker radeon_emit(cs, src->meta_va);
560*61046927SAndroid Build Coastguard Worker radeon_emit(cs, src->meta_va >> 32);
561*61046927SAndroid Build Coastguard Worker radeon_emit(cs, src->meta_config);
562*61046927SAndroid Build Coastguard Worker }
563*61046927SAndroid Build Coastguard Worker
564*61046927SAndroid Build Coastguard Worker assert(cs->cdw == cdw_end);
565*61046927SAndroid Build Coastguard Worker }
566*61046927SAndroid Build Coastguard Worker
567*61046927SAndroid Build Coastguard Worker void
radv_sdma_copy_buffer_image(const struct radv_device * device,struct radeon_cmdbuf * cs,const struct radv_sdma_surf * buf,const struct radv_sdma_surf * img,const VkExtent3D extent,bool to_image)568*61046927SAndroid Build Coastguard Worker radv_sdma_copy_buffer_image(const struct radv_device *device, struct radeon_cmdbuf *cs,
569*61046927SAndroid Build Coastguard Worker const struct radv_sdma_surf *buf, const struct radv_sdma_surf *img, const VkExtent3D extent,
570*61046927SAndroid Build Coastguard Worker bool to_image)
571*61046927SAndroid Build Coastguard Worker {
572*61046927SAndroid Build Coastguard Worker if (img->is_linear) {
573*61046927SAndroid Build Coastguard Worker if (to_image)
574*61046927SAndroid Build Coastguard Worker radv_sdma_emit_copy_linear_sub_window(device, cs, buf, img, extent);
575*61046927SAndroid Build Coastguard Worker else
576*61046927SAndroid Build Coastguard Worker radv_sdma_emit_copy_linear_sub_window(device, cs, img, buf, extent);
577*61046927SAndroid Build Coastguard Worker } else {
578*61046927SAndroid Build Coastguard Worker radv_sdma_emit_copy_tiled_sub_window(device, cs, img, buf, extent, !to_image);
579*61046927SAndroid Build Coastguard Worker }
580*61046927SAndroid Build Coastguard Worker }
581*61046927SAndroid Build Coastguard Worker
582*61046927SAndroid Build Coastguard Worker bool
radv_sdma_use_unaligned_buffer_image_copy(const struct radv_device * device,const struct radv_sdma_surf * buf,const struct radv_sdma_surf * img,const VkExtent3D ext)583*61046927SAndroid Build Coastguard Worker radv_sdma_use_unaligned_buffer_image_copy(const struct radv_device *device, const struct radv_sdma_surf *buf,
584*61046927SAndroid Build Coastguard Worker const struct radv_sdma_surf *img, const VkExtent3D ext)
585*61046927SAndroid Build Coastguard Worker {
586*61046927SAndroid Build Coastguard Worker const unsigned pitch_blocks = radv_sdma_pixels_to_blocks(buf->pitch, img->blk_w);
587*61046927SAndroid Build Coastguard Worker if (!util_is_aligned(pitch_blocks, radv_sdma_pitch_alignment(device, img->bpp)))
588*61046927SAndroid Build Coastguard Worker return true;
589*61046927SAndroid Build Coastguard Worker
590*61046927SAndroid Build Coastguard Worker const bool uses_depth = img->offset.z != 0 || ext.depth != 1;
591*61046927SAndroid Build Coastguard Worker if (!img->is_linear && uses_depth) {
592*61046927SAndroid Build Coastguard Worker const unsigned slice_pitch_blocks = radv_sdma_pixel_area_to_blocks(buf->slice_pitch, img->blk_w, img->blk_h);
593*61046927SAndroid Build Coastguard Worker if (!util_is_aligned(slice_pitch_blocks, 4))
594*61046927SAndroid Build Coastguard Worker return true;
595*61046927SAndroid Build Coastguard Worker }
596*61046927SAndroid Build Coastguard Worker
597*61046927SAndroid Build Coastguard Worker return false;
598*61046927SAndroid Build Coastguard Worker }
599*61046927SAndroid Build Coastguard Worker
600*61046927SAndroid Build Coastguard Worker void
radv_sdma_copy_buffer_image_unaligned(const struct radv_device * device,struct radeon_cmdbuf * cs,const struct radv_sdma_surf * buf,const struct radv_sdma_surf * img_in,const VkExtent3D base_extent,struct radeon_winsys_bo * temp_bo,bool to_image)601*61046927SAndroid Build Coastguard Worker radv_sdma_copy_buffer_image_unaligned(const struct radv_device *device, struct radeon_cmdbuf *cs,
602*61046927SAndroid Build Coastguard Worker const struct radv_sdma_surf *buf, const struct radv_sdma_surf *img_in,
603*61046927SAndroid Build Coastguard Worker const VkExtent3D base_extent, struct radeon_winsys_bo *temp_bo, bool to_image)
604*61046927SAndroid Build Coastguard Worker {
605*61046927SAndroid Build Coastguard Worker const struct radv_sdma_chunked_copy_info info = radv_sdma_get_chunked_copy_info(device, img_in, base_extent);
606*61046927SAndroid Build Coastguard Worker struct radv_sdma_surf img = *img_in;
607*61046927SAndroid Build Coastguard Worker struct radv_sdma_surf tmp = {
608*61046927SAndroid Build Coastguard Worker .va = temp_bo->va,
609*61046927SAndroid Build Coastguard Worker .bpp = img.bpp,
610*61046927SAndroid Build Coastguard Worker .blk_w = img.blk_w,
611*61046927SAndroid Build Coastguard Worker .blk_h = img.blk_h,
612*61046927SAndroid Build Coastguard Worker .pitch = info.aligned_row_pitch * img.blk_w,
613*61046927SAndroid Build Coastguard Worker .slice_pitch = info.aligned_row_pitch * img.blk_w * info.extent_vertical_blocks * img.blk_h,
614*61046927SAndroid Build Coastguard Worker };
615*61046927SAndroid Build Coastguard Worker
616*61046927SAndroid Build Coastguard Worker VkExtent3D extent = base_extent;
617*61046927SAndroid Build Coastguard Worker const unsigned buf_pitch_blocks = DIV_ROUND_UP(buf->pitch, img.blk_w);
618*61046927SAndroid Build Coastguard Worker const unsigned buf_slice_pitch_blocks = DIV_ROUND_UP(DIV_ROUND_UP(buf->slice_pitch, img.blk_w), img.blk_h);
619*61046927SAndroid Build Coastguard Worker assert(buf_pitch_blocks);
620*61046927SAndroid Build Coastguard Worker assert(buf_slice_pitch_blocks);
621*61046927SAndroid Build Coastguard Worker extent.depth = 1;
622*61046927SAndroid Build Coastguard Worker
623*61046927SAndroid Build Coastguard Worker for (unsigned slice = 0; slice < base_extent.depth; ++slice) {
624*61046927SAndroid Build Coastguard Worker for (unsigned row = 0; row < info.extent_vertical_blocks; row += info.num_rows_per_copy) {
625*61046927SAndroid Build Coastguard Worker const unsigned rows = MIN2(info.extent_vertical_blocks - row, info.num_rows_per_copy);
626*61046927SAndroid Build Coastguard Worker
627*61046927SAndroid Build Coastguard Worker img.offset.y = img_in->offset.y + row * img.blk_h;
628*61046927SAndroid Build Coastguard Worker img.offset.z = img_in->offset.z + slice;
629*61046927SAndroid Build Coastguard Worker extent.height = rows * img.blk_h;
630*61046927SAndroid Build Coastguard Worker tmp.slice_pitch = tmp.pitch * rows * img.blk_h;
631*61046927SAndroid Build Coastguard Worker
632*61046927SAndroid Build Coastguard Worker if (!to_image) {
633*61046927SAndroid Build Coastguard Worker /* Copy the rows from the source image to the temporary buffer. */
634*61046927SAndroid Build Coastguard Worker if (img.is_linear)
635*61046927SAndroid Build Coastguard Worker radv_sdma_emit_copy_linear_sub_window(device, cs, &img, &tmp, extent);
636*61046927SAndroid Build Coastguard Worker else
637*61046927SAndroid Build Coastguard Worker radv_sdma_emit_copy_tiled_sub_window(device, cs, &img, &tmp, extent, true);
638*61046927SAndroid Build Coastguard Worker
639*61046927SAndroid Build Coastguard Worker /* Wait for the copy to finish. */
640*61046927SAndroid Build Coastguard Worker radv_sdma_emit_nop(device, cs);
641*61046927SAndroid Build Coastguard Worker }
642*61046927SAndroid Build Coastguard Worker
643*61046927SAndroid Build Coastguard Worker /* buffer to image: copy each row from source buffer to temporary buffer.
644*61046927SAndroid Build Coastguard Worker * image to buffer: copy each row from temporary buffer to destination buffer.
645*61046927SAndroid Build Coastguard Worker */
646*61046927SAndroid Build Coastguard Worker for (unsigned r = 0; r < rows; ++r) {
647*61046927SAndroid Build Coastguard Worker const uint64_t buf_va =
648*61046927SAndroid Build Coastguard Worker buf->va + slice * buf_slice_pitch_blocks * img.bpp + (row + r) * buf_pitch_blocks * img.bpp;
649*61046927SAndroid Build Coastguard Worker const uint64_t tmp_va = tmp.va + r * info.aligned_row_pitch * img.bpp;
650*61046927SAndroid Build Coastguard Worker radv_sdma_copy_buffer(device, cs, to_image ? buf_va : tmp_va, to_image ? tmp_va : buf_va,
651*61046927SAndroid Build Coastguard Worker info.extent_horizontal_blocks * img.bpp);
652*61046927SAndroid Build Coastguard Worker }
653*61046927SAndroid Build Coastguard Worker
654*61046927SAndroid Build Coastguard Worker /* Wait for the copy to finish. */
655*61046927SAndroid Build Coastguard Worker radv_sdma_emit_nop(device, cs);
656*61046927SAndroid Build Coastguard Worker
657*61046927SAndroid Build Coastguard Worker if (to_image) {
658*61046927SAndroid Build Coastguard Worker /* Copy the rows from the temporary buffer to the destination image. */
659*61046927SAndroid Build Coastguard Worker if (img.is_linear)
660*61046927SAndroid Build Coastguard Worker radv_sdma_emit_copy_linear_sub_window(device, cs, &tmp, &img, extent);
661*61046927SAndroid Build Coastguard Worker else
662*61046927SAndroid Build Coastguard Worker radv_sdma_emit_copy_tiled_sub_window(device, cs, &img, &tmp, extent, false);
663*61046927SAndroid Build Coastguard Worker
664*61046927SAndroid Build Coastguard Worker /* Wait for the copy to finish. */
665*61046927SAndroid Build Coastguard Worker radv_sdma_emit_nop(device, cs);
666*61046927SAndroid Build Coastguard Worker }
667*61046927SAndroid Build Coastguard Worker }
668*61046927SAndroid Build Coastguard Worker }
669*61046927SAndroid Build Coastguard Worker }
670*61046927SAndroid Build Coastguard Worker
671*61046927SAndroid Build Coastguard Worker void
radv_sdma_copy_image(const struct radv_device * device,struct radeon_cmdbuf * cs,const struct radv_sdma_surf * src,const struct radv_sdma_surf * dst,const VkExtent3D extent)672*61046927SAndroid Build Coastguard Worker radv_sdma_copy_image(const struct radv_device *device, struct radeon_cmdbuf *cs, const struct radv_sdma_surf *src,
673*61046927SAndroid Build Coastguard Worker const struct radv_sdma_surf *dst, const VkExtent3D extent)
674*61046927SAndroid Build Coastguard Worker {
675*61046927SAndroid Build Coastguard Worker if (src->is_linear) {
676*61046927SAndroid Build Coastguard Worker if (dst->is_linear) {
677*61046927SAndroid Build Coastguard Worker radv_sdma_emit_copy_linear_sub_window(device, cs, src, dst, extent);
678*61046927SAndroid Build Coastguard Worker } else {
679*61046927SAndroid Build Coastguard Worker radv_sdma_emit_copy_tiled_sub_window(device, cs, dst, src, extent, false);
680*61046927SAndroid Build Coastguard Worker }
681*61046927SAndroid Build Coastguard Worker } else {
682*61046927SAndroid Build Coastguard Worker if (dst->is_linear) {
683*61046927SAndroid Build Coastguard Worker radv_sdma_emit_copy_tiled_sub_window(device, cs, src, dst, extent, true);
684*61046927SAndroid Build Coastguard Worker } else {
685*61046927SAndroid Build Coastguard Worker radv_sdma_emit_copy_t2t_sub_window(device, cs, src, dst, extent);
686*61046927SAndroid Build Coastguard Worker }
687*61046927SAndroid Build Coastguard Worker }
688*61046927SAndroid Build Coastguard Worker }
689*61046927SAndroid Build Coastguard Worker
690*61046927SAndroid Build Coastguard Worker bool
radv_sdma_use_t2t_scanline_copy(const struct radv_device * device,const struct radv_sdma_surf * src,const struct radv_sdma_surf * dst,const VkExtent3D extent)691*61046927SAndroid Build Coastguard Worker radv_sdma_use_t2t_scanline_copy(const struct radv_device *device, const struct radv_sdma_surf *src,
692*61046927SAndroid Build Coastguard Worker const struct radv_sdma_surf *dst, const VkExtent3D extent)
693*61046927SAndroid Build Coastguard Worker {
694*61046927SAndroid Build Coastguard Worker /* These need a linear-to-linear / linear-to-tiled copy. */
695*61046927SAndroid Build Coastguard Worker if (src->is_linear || dst->is_linear)
696*61046927SAndroid Build Coastguard Worker return false;
697*61046927SAndroid Build Coastguard Worker
698*61046927SAndroid Build Coastguard Worker /* SDMA can't do format conversion. */
699*61046927SAndroid Build Coastguard Worker assert(src->bpp == dst->bpp);
700*61046927SAndroid Build Coastguard Worker
701*61046927SAndroid Build Coastguard Worker const struct radv_physical_device *pdev = radv_device_physical(device);
702*61046927SAndroid Build Coastguard Worker const enum sdma_version ver = pdev->info.sdma_ip_version;
703*61046927SAndroid Build Coastguard Worker if (ver < SDMA_5_0) {
704*61046927SAndroid Build Coastguard Worker /* SDMA v4.x and older doesn't support proper mip level selection. */
705*61046927SAndroid Build Coastguard Worker if (src->mip_levels > 1 || dst->mip_levels > 1)
706*61046927SAndroid Build Coastguard Worker return true;
707*61046927SAndroid Build Coastguard Worker }
708*61046927SAndroid Build Coastguard Worker
709*61046927SAndroid Build Coastguard Worker /* The two images can have a different block size,
710*61046927SAndroid Build Coastguard Worker * but must have the same swizzle mode.
711*61046927SAndroid Build Coastguard Worker */
712*61046927SAndroid Build Coastguard Worker if (src->micro_tile_mode != dst->micro_tile_mode)
713*61046927SAndroid Build Coastguard Worker return true;
714*61046927SAndroid Build Coastguard Worker
715*61046927SAndroid Build Coastguard Worker /* The T2T subwindow copy packet only has fields for one metadata configuration.
716*61046927SAndroid Build Coastguard Worker * It can either compress or decompress, or copy uncompressed images, but it
717*61046927SAndroid Build Coastguard Worker * can't copy from a compressed image to another.
718*61046927SAndroid Build Coastguard Worker */
719*61046927SAndroid Build Coastguard Worker if (src->meta_va && dst->meta_va)
720*61046927SAndroid Build Coastguard Worker return true;
721*61046927SAndroid Build Coastguard Worker
722*61046927SAndroid Build Coastguard Worker const bool needs_3d_alignment = src->is_3d && (src->micro_tile_mode == RADEON_MICRO_MODE_DISPLAY ||
723*61046927SAndroid Build Coastguard Worker src->micro_tile_mode == RADEON_MICRO_MODE_STANDARD);
724*61046927SAndroid Build Coastguard Worker const unsigned log2bpp = util_logbase2(src->bpp);
725*61046927SAndroid Build Coastguard Worker const VkExtent3D *const alignment =
726*61046927SAndroid Build Coastguard Worker needs_3d_alignment ? &radv_sdma_t2t_alignment_3d[log2bpp] : &radv_sdma_t2t_alignment_2d_and_planar[log2bpp];
727*61046927SAndroid Build Coastguard Worker
728*61046927SAndroid Build Coastguard Worker const VkExtent3D copy_extent_blk = radv_sdma_pixel_extent_to_blocks(extent, src->blk_w, src->blk_h);
729*61046927SAndroid Build Coastguard Worker const VkOffset3D src_offset_blk = radv_sdma_pixel_offset_to_blocks(src->offset, src->blk_w, src->blk_h);
730*61046927SAndroid Build Coastguard Worker const VkOffset3D dst_offset_blk = radv_sdma_pixel_offset_to_blocks(dst->offset, dst->blk_w, dst->blk_h);
731*61046927SAndroid Build Coastguard Worker
732*61046927SAndroid Build Coastguard Worker if (!util_is_aligned(copy_extent_blk.width, alignment->width) ||
733*61046927SAndroid Build Coastguard Worker !util_is_aligned(copy_extent_blk.height, alignment->height) ||
734*61046927SAndroid Build Coastguard Worker !util_is_aligned(copy_extent_blk.depth, alignment->depth))
735*61046927SAndroid Build Coastguard Worker return true;
736*61046927SAndroid Build Coastguard Worker
737*61046927SAndroid Build Coastguard Worker if (!util_is_aligned(src_offset_blk.x, alignment->width) || !util_is_aligned(src_offset_blk.y, alignment->height) ||
738*61046927SAndroid Build Coastguard Worker !util_is_aligned(src_offset_blk.z, alignment->depth))
739*61046927SAndroid Build Coastguard Worker return true;
740*61046927SAndroid Build Coastguard Worker
741*61046927SAndroid Build Coastguard Worker if (!util_is_aligned(dst_offset_blk.x, alignment->width) || !util_is_aligned(dst_offset_blk.y, alignment->height) ||
742*61046927SAndroid Build Coastguard Worker !util_is_aligned(dst_offset_blk.z, alignment->depth))
743*61046927SAndroid Build Coastguard Worker return true;
744*61046927SAndroid Build Coastguard Worker
745*61046927SAndroid Build Coastguard Worker return false;
746*61046927SAndroid Build Coastguard Worker }
747*61046927SAndroid Build Coastguard Worker
748*61046927SAndroid Build Coastguard Worker void
radv_sdma_copy_image_t2t_scanline(const struct radv_device * device,struct radeon_cmdbuf * cs,const struct radv_sdma_surf * src,const struct radv_sdma_surf * dst,const VkExtent3D extent,struct radeon_winsys_bo * temp_bo)749*61046927SAndroid Build Coastguard Worker radv_sdma_copy_image_t2t_scanline(const struct radv_device *device, struct radeon_cmdbuf *cs,
750*61046927SAndroid Build Coastguard Worker const struct radv_sdma_surf *src, const struct radv_sdma_surf *dst,
751*61046927SAndroid Build Coastguard Worker const VkExtent3D extent, struct radeon_winsys_bo *temp_bo)
752*61046927SAndroid Build Coastguard Worker {
753*61046927SAndroid Build Coastguard Worker const struct radv_sdma_chunked_copy_info info = radv_sdma_get_chunked_copy_info(device, src, extent);
754*61046927SAndroid Build Coastguard Worker struct radv_sdma_surf t2l_src = *src;
755*61046927SAndroid Build Coastguard Worker struct radv_sdma_surf t2l_dst = {
756*61046927SAndroid Build Coastguard Worker .va = temp_bo->va,
757*61046927SAndroid Build Coastguard Worker .bpp = src->bpp,
758*61046927SAndroid Build Coastguard Worker .blk_w = src->blk_w,
759*61046927SAndroid Build Coastguard Worker .blk_h = src->blk_h,
760*61046927SAndroid Build Coastguard Worker .pitch = info.aligned_row_pitch * src->blk_w,
761*61046927SAndroid Build Coastguard Worker };
762*61046927SAndroid Build Coastguard Worker struct radv_sdma_surf l2t_dst = *dst;
763*61046927SAndroid Build Coastguard Worker struct radv_sdma_surf l2t_src = {
764*61046927SAndroid Build Coastguard Worker .va = temp_bo->va,
765*61046927SAndroid Build Coastguard Worker .bpp = dst->bpp,
766*61046927SAndroid Build Coastguard Worker .blk_w = dst->blk_w,
767*61046927SAndroid Build Coastguard Worker .blk_h = dst->blk_h,
768*61046927SAndroid Build Coastguard Worker .pitch = info.aligned_row_pitch * dst->blk_w,
769*61046927SAndroid Build Coastguard Worker };
770*61046927SAndroid Build Coastguard Worker
771*61046927SAndroid Build Coastguard Worker for (unsigned slice = 0; slice < extent.depth; ++slice) {
772*61046927SAndroid Build Coastguard Worker for (unsigned row = 0; row < info.extent_vertical_blocks; row += info.num_rows_per_copy) {
773*61046927SAndroid Build Coastguard Worker const unsigned rows = MIN2(info.extent_vertical_blocks - row, info.num_rows_per_copy);
774*61046927SAndroid Build Coastguard Worker
775*61046927SAndroid Build Coastguard Worker const VkExtent3D t2l_extent = {
776*61046927SAndroid Build Coastguard Worker .width = info.extent_horizontal_blocks * src->blk_w,
777*61046927SAndroid Build Coastguard Worker .height = rows * src->blk_h,
778*61046927SAndroid Build Coastguard Worker .depth = 1,
779*61046927SAndroid Build Coastguard Worker };
780*61046927SAndroid Build Coastguard Worker
781*61046927SAndroid Build Coastguard Worker t2l_src.offset.y = src->offset.y + row * src->blk_h;
782*61046927SAndroid Build Coastguard Worker t2l_src.offset.z = src->offset.z + slice;
783*61046927SAndroid Build Coastguard Worker t2l_dst.slice_pitch = t2l_dst.pitch * t2l_extent.height;
784*61046927SAndroid Build Coastguard Worker
785*61046927SAndroid Build Coastguard Worker radv_sdma_emit_copy_tiled_sub_window(device, cs, &t2l_src, &t2l_dst, t2l_extent, true);
786*61046927SAndroid Build Coastguard Worker radv_sdma_emit_nop(device, cs);
787*61046927SAndroid Build Coastguard Worker
788*61046927SAndroid Build Coastguard Worker const VkExtent3D l2t_extent = {
789*61046927SAndroid Build Coastguard Worker .width = info.extent_horizontal_blocks * dst->blk_w,
790*61046927SAndroid Build Coastguard Worker .height = rows * dst->blk_h,
791*61046927SAndroid Build Coastguard Worker .depth = 1,
792*61046927SAndroid Build Coastguard Worker };
793*61046927SAndroid Build Coastguard Worker
794*61046927SAndroid Build Coastguard Worker l2t_dst.offset.y = dst->offset.y + row * dst->blk_h;
795*61046927SAndroid Build Coastguard Worker l2t_dst.offset.z = dst->offset.z + slice;
796*61046927SAndroid Build Coastguard Worker l2t_src.slice_pitch = l2t_src.pitch * l2t_extent.height;
797*61046927SAndroid Build Coastguard Worker
798*61046927SAndroid Build Coastguard Worker radv_sdma_emit_copy_tiled_sub_window(device, cs, &l2t_dst, &l2t_src, l2t_extent, false);
799*61046927SAndroid Build Coastguard Worker radv_sdma_emit_nop(device, cs);
800*61046927SAndroid Build Coastguard Worker }
801*61046927SAndroid Build Coastguard Worker }
802*61046927SAndroid Build Coastguard Worker }
803