xref: /aosp_15_r20/external/mesa3d/src/amd/vulkan/radv_image.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright © 2016 Red Hat.
3*61046927SAndroid Build Coastguard Worker  * Copyright © 2016 Bas Nieuwenhuizen
4*61046927SAndroid Build Coastguard Worker  *
5*61046927SAndroid Build Coastguard Worker  * based in part on anv driver which is:
6*61046927SAndroid Build Coastguard Worker  * Copyright © 2015 Intel Corporation
7*61046927SAndroid Build Coastguard Worker  *
8*61046927SAndroid Build Coastguard Worker  * SPDX-License-Identifier: MIT
9*61046927SAndroid Build Coastguard Worker  */
10*61046927SAndroid Build Coastguard Worker 
11*61046927SAndroid Build Coastguard Worker #include "radv_image.h"
12*61046927SAndroid Build Coastguard Worker #include "util/u_atomic.h"
13*61046927SAndroid Build Coastguard Worker #include "util/u_debug.h"
14*61046927SAndroid Build Coastguard Worker #include "ac_drm_fourcc.h"
15*61046927SAndroid Build Coastguard Worker #include "ac_formats.h"
16*61046927SAndroid Build Coastguard Worker #include "radv_android.h"
17*61046927SAndroid Build Coastguard Worker #include "radv_buffer.h"
18*61046927SAndroid Build Coastguard Worker #include "radv_buffer_view.h"
19*61046927SAndroid Build Coastguard Worker #include "radv_debug.h"
20*61046927SAndroid Build Coastguard Worker #include "radv_device_memory.h"
21*61046927SAndroid Build Coastguard Worker #include "radv_entrypoints.h"
22*61046927SAndroid Build Coastguard Worker #include "radv_formats.h"
23*61046927SAndroid Build Coastguard Worker #include "radv_image_view.h"
24*61046927SAndroid Build Coastguard Worker #include "radv_radeon_winsys.h"
25*61046927SAndroid Build Coastguard Worker #include "radv_rmv.h"
26*61046927SAndroid Build Coastguard Worker #include "radv_video.h"
27*61046927SAndroid Build Coastguard Worker #include "radv_wsi.h"
28*61046927SAndroid Build Coastguard Worker #include "sid.h"
29*61046927SAndroid Build Coastguard Worker #include "vk_debug_utils.h"
30*61046927SAndroid Build Coastguard Worker #include "vk_format.h"
31*61046927SAndroid Build Coastguard Worker #include "vk_log.h"
32*61046927SAndroid Build Coastguard Worker #include "vk_render_pass.h"
33*61046927SAndroid Build Coastguard Worker #include "vk_util.h"
34*61046927SAndroid Build Coastguard Worker 
35*61046927SAndroid Build Coastguard Worker #include "gfx10_format_table.h"
36*61046927SAndroid Build Coastguard Worker 
37*61046927SAndroid Build Coastguard Worker static unsigned
radv_choose_tiling(struct radv_device * device,const VkImageCreateInfo * pCreateInfo,VkFormat format)38*61046927SAndroid Build Coastguard Worker radv_choose_tiling(struct radv_device *device, const VkImageCreateInfo *pCreateInfo, VkFormat format)
39*61046927SAndroid Build Coastguard Worker {
40*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
41*61046927SAndroid Build Coastguard Worker 
42*61046927SAndroid Build Coastguard Worker    if (pCreateInfo->tiling == VK_IMAGE_TILING_LINEAR) {
43*61046927SAndroid Build Coastguard Worker       assert(pCreateInfo->samples <= 1);
44*61046927SAndroid Build Coastguard Worker       return RADEON_SURF_MODE_LINEAR_ALIGNED;
45*61046927SAndroid Build Coastguard Worker    }
46*61046927SAndroid Build Coastguard Worker 
47*61046927SAndroid Build Coastguard Worker    if (pCreateInfo->usage & (VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR | VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR))
48*61046927SAndroid Build Coastguard Worker       return RADEON_SURF_MODE_LINEAR_ALIGNED;
49*61046927SAndroid Build Coastguard Worker 
50*61046927SAndroid Build Coastguard Worker    if (pCreateInfo->usage & (VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR | VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR))
51*61046927SAndroid Build Coastguard Worker       return RADEON_SURF_MODE_LINEAR_ALIGNED;
52*61046927SAndroid Build Coastguard Worker 
53*61046927SAndroid Build Coastguard Worker    /* MSAA resources must be 2D tiled. */
54*61046927SAndroid Build Coastguard Worker    if (pCreateInfo->samples > 1)
55*61046927SAndroid Build Coastguard Worker       return RADEON_SURF_MODE_2D;
56*61046927SAndroid Build Coastguard Worker 
57*61046927SAndroid Build Coastguard Worker    if (!vk_format_is_compressed(format) && !vk_format_is_depth_or_stencil(format) && pdev->info.gfx_level <= GFX8) {
58*61046927SAndroid Build Coastguard Worker       /* this causes hangs in some VK CTS tests on GFX9. */
59*61046927SAndroid Build Coastguard Worker       /* Textures with a very small height are recommended to be linear. */
60*61046927SAndroid Build Coastguard Worker       if (pCreateInfo->imageType == VK_IMAGE_TYPE_1D ||
61*61046927SAndroid Build Coastguard Worker           /* Only very thin and long 2D textures should benefit from
62*61046927SAndroid Build Coastguard Worker            * linear_aligned. */
63*61046927SAndroid Build Coastguard Worker           (pCreateInfo->extent.width > 8 && pCreateInfo->extent.height <= 2))
64*61046927SAndroid Build Coastguard Worker          return RADEON_SURF_MODE_LINEAR_ALIGNED;
65*61046927SAndroid Build Coastguard Worker    }
66*61046927SAndroid Build Coastguard Worker 
67*61046927SAndroid Build Coastguard Worker    return RADEON_SURF_MODE_2D;
68*61046927SAndroid Build Coastguard Worker }
69*61046927SAndroid Build Coastguard Worker 
70*61046927SAndroid Build Coastguard Worker static bool
radv_use_tc_compat_htile_for_image(struct radv_device * device,const VkImageCreateInfo * pCreateInfo,VkFormat format)71*61046927SAndroid Build Coastguard Worker radv_use_tc_compat_htile_for_image(struct radv_device *device, const VkImageCreateInfo *pCreateInfo, VkFormat format)
72*61046927SAndroid Build Coastguard Worker {
73*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
74*61046927SAndroid Build Coastguard Worker 
75*61046927SAndroid Build Coastguard Worker    if (!pdev->info.has_tc_compatible_htile)
76*61046927SAndroid Build Coastguard Worker       return false;
77*61046927SAndroid Build Coastguard Worker 
78*61046927SAndroid Build Coastguard Worker    /* TC-compat HTILE looks broken on Tonga (and Iceland is the same design) and the documented bug
79*61046927SAndroid Build Coastguard Worker     * workarounds don't help.
80*61046927SAndroid Build Coastguard Worker     */
81*61046927SAndroid Build Coastguard Worker    if (pdev->info.family == CHIP_TONGA || pdev->info.family == CHIP_ICELAND)
82*61046927SAndroid Build Coastguard Worker       return false;
83*61046927SAndroid Build Coastguard Worker 
84*61046927SAndroid Build Coastguard Worker    if (pCreateInfo->tiling == VK_IMAGE_TILING_LINEAR)
85*61046927SAndroid Build Coastguard Worker       return false;
86*61046927SAndroid Build Coastguard Worker 
87*61046927SAndroid Build Coastguard Worker    /* Do not enable TC-compatible HTILE if the image isn't readable by a
88*61046927SAndroid Build Coastguard Worker     * shader because no texture fetches will happen.
89*61046927SAndroid Build Coastguard Worker     */
90*61046927SAndroid Build Coastguard Worker    if (!(pCreateInfo->usage &
91*61046927SAndroid Build Coastguard Worker          (VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)))
92*61046927SAndroid Build Coastguard Worker       return false;
93*61046927SAndroid Build Coastguard Worker 
94*61046927SAndroid Build Coastguard Worker    if (pdev->info.gfx_level < GFX9) {
95*61046927SAndroid Build Coastguard Worker       /* TC-compat HTILE for MSAA depth/stencil images is broken
96*61046927SAndroid Build Coastguard Worker        * on GFX8 because the tiling doesn't match.
97*61046927SAndroid Build Coastguard Worker        */
98*61046927SAndroid Build Coastguard Worker       if (pCreateInfo->samples >= 2 && format == VK_FORMAT_D32_SFLOAT_S8_UINT)
99*61046927SAndroid Build Coastguard Worker          return false;
100*61046927SAndroid Build Coastguard Worker 
101*61046927SAndroid Build Coastguard Worker       /* GFX9+ supports compression for both 32-bit and 16-bit depth
102*61046927SAndroid Build Coastguard Worker        * surfaces, while GFX8 only supports 32-bit natively. Though,
103*61046927SAndroid Build Coastguard Worker        * the driver allows TC-compat HTILE for 16-bit depth surfaces
104*61046927SAndroid Build Coastguard Worker        * with no Z planes compression.
105*61046927SAndroid Build Coastguard Worker        */
106*61046927SAndroid Build Coastguard Worker       if (format != VK_FORMAT_D32_SFLOAT_S8_UINT && format != VK_FORMAT_D32_SFLOAT && format != VK_FORMAT_D16_UNORM)
107*61046927SAndroid Build Coastguard Worker          return false;
108*61046927SAndroid Build Coastguard Worker 
109*61046927SAndroid Build Coastguard Worker       /* TC-compat HTILE for layered images can have interleaved slices (see sliceInterleaved flag
110*61046927SAndroid Build Coastguard Worker        * in addrlib).  radv_clear_htile does not work.
111*61046927SAndroid Build Coastguard Worker        */
112*61046927SAndroid Build Coastguard Worker       if (pCreateInfo->arrayLayers > 1)
113*61046927SAndroid Build Coastguard Worker          return false;
114*61046927SAndroid Build Coastguard Worker    }
115*61046927SAndroid Build Coastguard Worker 
116*61046927SAndroid Build Coastguard Worker    /* GFX9 has issues when the sample count is 4 and the format is D16 */
117*61046927SAndroid Build Coastguard Worker    if (pdev->info.gfx_level == GFX9 && pCreateInfo->samples == 4 && format == VK_FORMAT_D16_UNORM)
118*61046927SAndroid Build Coastguard Worker       return false;
119*61046927SAndroid Build Coastguard Worker 
120*61046927SAndroid Build Coastguard Worker    return true;
121*61046927SAndroid Build Coastguard Worker }
122*61046927SAndroid Build Coastguard Worker 
123*61046927SAndroid Build Coastguard Worker static bool
radv_surface_has_scanout(struct radv_device * device,const struct radv_image_create_info * info)124*61046927SAndroid Build Coastguard Worker radv_surface_has_scanout(struct radv_device *device, const struct radv_image_create_info *info)
125*61046927SAndroid Build Coastguard Worker {
126*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
127*61046927SAndroid Build Coastguard Worker 
128*61046927SAndroid Build Coastguard Worker    if (info->bo_metadata) {
129*61046927SAndroid Build Coastguard Worker       if (pdev->info.gfx_level >= GFX9)
130*61046927SAndroid Build Coastguard Worker          return info->bo_metadata->u.gfx9.scanout;
131*61046927SAndroid Build Coastguard Worker       else
132*61046927SAndroid Build Coastguard Worker          return info->bo_metadata->u.legacy.scanout;
133*61046927SAndroid Build Coastguard Worker    }
134*61046927SAndroid Build Coastguard Worker 
135*61046927SAndroid Build Coastguard Worker    return info->scanout;
136*61046927SAndroid Build Coastguard Worker }
137*61046927SAndroid Build Coastguard Worker 
138*61046927SAndroid Build Coastguard Worker static bool
radv_image_use_fast_clear_for_image_early(const struct radv_device * device,const struct radv_image * image)139*61046927SAndroid Build Coastguard Worker radv_image_use_fast_clear_for_image_early(const struct radv_device *device, const struct radv_image *image)
140*61046927SAndroid Build Coastguard Worker {
141*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
142*61046927SAndroid Build Coastguard Worker    const struct radv_instance *instance = radv_physical_device_instance(pdev);
143*61046927SAndroid Build Coastguard Worker 
144*61046927SAndroid Build Coastguard Worker    if (instance->debug_flags & RADV_DEBUG_FORCE_COMPRESS)
145*61046927SAndroid Build Coastguard Worker       return true;
146*61046927SAndroid Build Coastguard Worker 
147*61046927SAndroid Build Coastguard Worker    if (image->vk.samples <= 1 && image->vk.extent.width * image->vk.extent.height <= 512 * 512) {
148*61046927SAndroid Build Coastguard Worker       /* Do not enable CMASK or DCC for small surfaces where the cost
149*61046927SAndroid Build Coastguard Worker        * of the eliminate pass can be higher than the benefit of fast
150*61046927SAndroid Build Coastguard Worker        * clear. RadeonSI does this, but the image threshold is
151*61046927SAndroid Build Coastguard Worker        * different.
152*61046927SAndroid Build Coastguard Worker        */
153*61046927SAndroid Build Coastguard Worker       return false;
154*61046927SAndroid Build Coastguard Worker    }
155*61046927SAndroid Build Coastguard Worker 
156*61046927SAndroid Build Coastguard Worker    return !!(image->vk.usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
157*61046927SAndroid Build Coastguard Worker }
158*61046927SAndroid Build Coastguard Worker 
159*61046927SAndroid Build Coastguard Worker static bool
radv_image_use_fast_clear_for_image(const struct radv_device * device,const struct radv_image * image)160*61046927SAndroid Build Coastguard Worker radv_image_use_fast_clear_for_image(const struct radv_device *device, const struct radv_image *image)
161*61046927SAndroid Build Coastguard Worker {
162*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
163*61046927SAndroid Build Coastguard Worker    const struct radv_instance *instance = radv_physical_device_instance(pdev);
164*61046927SAndroid Build Coastguard Worker 
165*61046927SAndroid Build Coastguard Worker    if (instance->debug_flags & RADV_DEBUG_FORCE_COMPRESS)
166*61046927SAndroid Build Coastguard Worker       return true;
167*61046927SAndroid Build Coastguard Worker 
168*61046927SAndroid Build Coastguard Worker    return radv_image_use_fast_clear_for_image_early(device, image) && (image->exclusive ||
169*61046927SAndroid Build Coastguard Worker                                                                        /* Enable DCC for concurrent images if stores are
170*61046927SAndroid Build Coastguard Worker                                                                         * supported because that means we can keep DCC
171*61046927SAndroid Build Coastguard Worker                                                                         * compressed on all layouts/queues.
172*61046927SAndroid Build Coastguard Worker                                                                         */
173*61046927SAndroid Build Coastguard Worker                                                                        radv_image_use_dcc_image_stores(device, image));
174*61046927SAndroid Build Coastguard Worker }
175*61046927SAndroid Build Coastguard Worker 
176*61046927SAndroid Build Coastguard Worker bool
radv_are_formats_dcc_compatible(const struct radv_physical_device * pdev,const void * pNext,VkFormat format,VkImageCreateFlags flags,bool * sign_reinterpret)177*61046927SAndroid Build Coastguard Worker radv_are_formats_dcc_compatible(const struct radv_physical_device *pdev, const void *pNext, VkFormat format,
178*61046927SAndroid Build Coastguard Worker                                 VkImageCreateFlags flags, bool *sign_reinterpret)
179*61046927SAndroid Build Coastguard Worker {
180*61046927SAndroid Build Coastguard Worker    if (!radv_is_colorbuffer_format_supported(pdev, format))
181*61046927SAndroid Build Coastguard Worker       return false;
182*61046927SAndroid Build Coastguard Worker 
183*61046927SAndroid Build Coastguard Worker    if (sign_reinterpret != NULL)
184*61046927SAndroid Build Coastguard Worker       *sign_reinterpret = false;
185*61046927SAndroid Build Coastguard Worker 
186*61046927SAndroid Build Coastguard Worker    /* All formats are compatible on GFX11. */
187*61046927SAndroid Build Coastguard Worker    if ((flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) && pdev->info.gfx_level < GFX11) {
188*61046927SAndroid Build Coastguard Worker       const struct VkImageFormatListCreateInfo *format_list =
189*61046927SAndroid Build Coastguard Worker          (const struct VkImageFormatListCreateInfo *)vk_find_struct_const(pNext, IMAGE_FORMAT_LIST_CREATE_INFO);
190*61046927SAndroid Build Coastguard Worker 
191*61046927SAndroid Build Coastguard Worker       /* We have to ignore the existence of the list if viewFormatCount = 0 */
192*61046927SAndroid Build Coastguard Worker       if (format_list && format_list->viewFormatCount) {
193*61046927SAndroid Build Coastguard Worker          /* compatibility is transitive, so we only need to check
194*61046927SAndroid Build Coastguard Worker           * one format with everything else. */
195*61046927SAndroid Build Coastguard Worker          for (unsigned i = 0; i < format_list->viewFormatCount; ++i) {
196*61046927SAndroid Build Coastguard Worker             if (format_list->pViewFormats[i] == VK_FORMAT_UNDEFINED)
197*61046927SAndroid Build Coastguard Worker                continue;
198*61046927SAndroid Build Coastguard Worker 
199*61046927SAndroid Build Coastguard Worker             if (!radv_dcc_formats_compatible(pdev->info.gfx_level, format, format_list->pViewFormats[i],
200*61046927SAndroid Build Coastguard Worker                                              sign_reinterpret))
201*61046927SAndroid Build Coastguard Worker                return false;
202*61046927SAndroid Build Coastguard Worker          }
203*61046927SAndroid Build Coastguard Worker       } else {
204*61046927SAndroid Build Coastguard Worker          return false;
205*61046927SAndroid Build Coastguard Worker       }
206*61046927SAndroid Build Coastguard Worker    }
207*61046927SAndroid Build Coastguard Worker 
208*61046927SAndroid Build Coastguard Worker    return true;
209*61046927SAndroid Build Coastguard Worker }
210*61046927SAndroid Build Coastguard Worker 
211*61046927SAndroid Build Coastguard Worker static bool
radv_format_is_atomic_allowed(struct radv_device * device,VkFormat format)212*61046927SAndroid Build Coastguard Worker radv_format_is_atomic_allowed(struct radv_device *device, VkFormat format)
213*61046927SAndroid Build Coastguard Worker {
214*61046927SAndroid Build Coastguard Worker    if (format == VK_FORMAT_R32_SFLOAT && !radv_uses_image_float32_atomics(device))
215*61046927SAndroid Build Coastguard Worker       return false;
216*61046927SAndroid Build Coastguard Worker 
217*61046927SAndroid Build Coastguard Worker    return radv_is_atomic_format_supported(format);
218*61046927SAndroid Build Coastguard Worker }
219*61046927SAndroid Build Coastguard Worker 
220*61046927SAndroid Build Coastguard Worker static bool
radv_formats_is_atomic_allowed(struct radv_device * device,const void * pNext,VkFormat format,VkImageCreateFlags flags)221*61046927SAndroid Build Coastguard Worker radv_formats_is_atomic_allowed(struct radv_device *device, const void *pNext, VkFormat format, VkImageCreateFlags flags)
222*61046927SAndroid Build Coastguard Worker {
223*61046927SAndroid Build Coastguard Worker    if (radv_format_is_atomic_allowed(device, format))
224*61046927SAndroid Build Coastguard Worker       return true;
225*61046927SAndroid Build Coastguard Worker 
226*61046927SAndroid Build Coastguard Worker    if (flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) {
227*61046927SAndroid Build Coastguard Worker       const struct VkImageFormatListCreateInfo *format_list =
228*61046927SAndroid Build Coastguard Worker          (const struct VkImageFormatListCreateInfo *)vk_find_struct_const(pNext, IMAGE_FORMAT_LIST_CREATE_INFO);
229*61046927SAndroid Build Coastguard Worker 
230*61046927SAndroid Build Coastguard Worker       /* We have to ignore the existence of the list if viewFormatCount = 0 */
231*61046927SAndroid Build Coastguard Worker       if (format_list && format_list->viewFormatCount) {
232*61046927SAndroid Build Coastguard Worker          for (unsigned i = 0; i < format_list->viewFormatCount; ++i) {
233*61046927SAndroid Build Coastguard Worker             if (radv_format_is_atomic_allowed(device, format_list->pViewFormats[i]))
234*61046927SAndroid Build Coastguard Worker                return true;
235*61046927SAndroid Build Coastguard Worker          }
236*61046927SAndroid Build Coastguard Worker       }
237*61046927SAndroid Build Coastguard Worker    }
238*61046927SAndroid Build Coastguard Worker 
239*61046927SAndroid Build Coastguard Worker    return false;
240*61046927SAndroid Build Coastguard Worker }
241*61046927SAndroid Build Coastguard Worker 
242*61046927SAndroid Build Coastguard Worker static bool
radv_use_dcc_for_image_early(struct radv_device * device,struct radv_image * image,const VkImageCreateInfo * pCreateInfo,VkFormat format,bool * sign_reinterpret)243*61046927SAndroid Build Coastguard Worker radv_use_dcc_for_image_early(struct radv_device *device, struct radv_image *image, const VkImageCreateInfo *pCreateInfo,
244*61046927SAndroid Build Coastguard Worker                              VkFormat format, bool *sign_reinterpret)
245*61046927SAndroid Build Coastguard Worker {
246*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
247*61046927SAndroid Build Coastguard Worker    const struct radv_instance *instance = radv_physical_device_instance(pdev);
248*61046927SAndroid Build Coastguard Worker 
249*61046927SAndroid Build Coastguard Worker    /* DCC (Delta Color Compression) is only available for GFX8+. */
250*61046927SAndroid Build Coastguard Worker    if (pdev->info.gfx_level < GFX8)
251*61046927SAndroid Build Coastguard Worker       return false;
252*61046927SAndroid Build Coastguard Worker 
253*61046927SAndroid Build Coastguard Worker    const VkImageCompressionControlEXT *compression =
254*61046927SAndroid Build Coastguard Worker       vk_find_struct_const(pCreateInfo->pNext, IMAGE_COMPRESSION_CONTROL_EXT);
255*61046927SAndroid Build Coastguard Worker 
256*61046927SAndroid Build Coastguard Worker    if (instance->debug_flags & RADV_DEBUG_NO_DCC ||
257*61046927SAndroid Build Coastguard Worker        (compression && compression->flags == VK_IMAGE_COMPRESSION_DISABLED_EXT)) {
258*61046927SAndroid Build Coastguard Worker       return false;
259*61046927SAndroid Build Coastguard Worker    }
260*61046927SAndroid Build Coastguard Worker 
261*61046927SAndroid Build Coastguard Worker    if (image->shareable && image->vk.tiling != VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT)
262*61046927SAndroid Build Coastguard Worker       return false;
263*61046927SAndroid Build Coastguard Worker 
264*61046927SAndroid Build Coastguard Worker    /*
265*61046927SAndroid Build Coastguard Worker     * TODO: Enable DCC for storage images on GFX9 and earlier.
266*61046927SAndroid Build Coastguard Worker     *
267*61046927SAndroid Build Coastguard Worker     * Also disable DCC with atomics because even when DCC stores are
268*61046927SAndroid Build Coastguard Worker     * supported atomics will always decompress. So if we are
269*61046927SAndroid Build Coastguard Worker     * decompressing a lot anyway we might as well not have DCC.
270*61046927SAndroid Build Coastguard Worker     */
271*61046927SAndroid Build Coastguard Worker    if ((pCreateInfo->usage & VK_IMAGE_USAGE_STORAGE_BIT) &&
272*61046927SAndroid Build Coastguard Worker        (pdev->info.gfx_level < GFX10 ||
273*61046927SAndroid Build Coastguard Worker         radv_formats_is_atomic_allowed(device, pCreateInfo->pNext, format, pCreateInfo->flags)))
274*61046927SAndroid Build Coastguard Worker       return false;
275*61046927SAndroid Build Coastguard Worker 
276*61046927SAndroid Build Coastguard Worker    if (pCreateInfo->tiling == VK_IMAGE_TILING_LINEAR)
277*61046927SAndroid Build Coastguard Worker       return false;
278*61046927SAndroid Build Coastguard Worker 
279*61046927SAndroid Build Coastguard Worker    if (vk_format_is_subsampled(format) || vk_format_get_plane_count(format) > 1)
280*61046927SAndroid Build Coastguard Worker       return false;
281*61046927SAndroid Build Coastguard Worker 
282*61046927SAndroid Build Coastguard Worker    if (!radv_image_use_fast_clear_for_image_early(device, image) &&
283*61046927SAndroid Build Coastguard Worker        image->vk.tiling != VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT)
284*61046927SAndroid Build Coastguard Worker       return false;
285*61046927SAndroid Build Coastguard Worker 
286*61046927SAndroid Build Coastguard Worker    /* Do not enable DCC for mipmapped arrays because performance is worse. */
287*61046927SAndroid Build Coastguard Worker    if (pCreateInfo->arrayLayers > 1 && pCreateInfo->mipLevels > 1)
288*61046927SAndroid Build Coastguard Worker       return false;
289*61046927SAndroid Build Coastguard Worker 
290*61046927SAndroid Build Coastguard Worker    if (pdev->info.gfx_level < GFX10) {
291*61046927SAndroid Build Coastguard Worker       /* TODO: Add support for DCC MSAA on GFX8-9. */
292*61046927SAndroid Build Coastguard Worker       if (pCreateInfo->samples > 1 && !pdev->dcc_msaa_allowed)
293*61046927SAndroid Build Coastguard Worker          return false;
294*61046927SAndroid Build Coastguard Worker 
295*61046927SAndroid Build Coastguard Worker       /* TODO: Add support for DCC layers/mipmaps on GFX9. */
296*61046927SAndroid Build Coastguard Worker       if ((pCreateInfo->arrayLayers > 1 || pCreateInfo->mipLevels > 1) && pdev->info.gfx_level == GFX9)
297*61046927SAndroid Build Coastguard Worker          return false;
298*61046927SAndroid Build Coastguard Worker    }
299*61046927SAndroid Build Coastguard Worker 
300*61046927SAndroid Build Coastguard Worker    /* DCC MSAA can't work on GFX10.3 and earlier without FMASK. */
301*61046927SAndroid Build Coastguard Worker    if (pCreateInfo->samples > 1 && pdev->info.gfx_level < GFX11 && (instance->debug_flags & RADV_DEBUG_NO_FMASK))
302*61046927SAndroid Build Coastguard Worker       return false;
303*61046927SAndroid Build Coastguard Worker 
304*61046927SAndroid Build Coastguard Worker    return radv_are_formats_dcc_compatible(pdev, pCreateInfo->pNext, format, pCreateInfo->flags, sign_reinterpret);
305*61046927SAndroid Build Coastguard Worker }
306*61046927SAndroid Build Coastguard Worker 
307*61046927SAndroid Build Coastguard Worker static bool
radv_use_dcc_for_image_late(struct radv_device * device,struct radv_image * image)308*61046927SAndroid Build Coastguard Worker radv_use_dcc_for_image_late(struct radv_device *device, struct radv_image *image)
309*61046927SAndroid Build Coastguard Worker {
310*61046927SAndroid Build Coastguard Worker    if (!radv_image_has_dcc(image))
311*61046927SAndroid Build Coastguard Worker       return false;
312*61046927SAndroid Build Coastguard Worker 
313*61046927SAndroid Build Coastguard Worker    if (image->vk.tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT)
314*61046927SAndroid Build Coastguard Worker       return true;
315*61046927SAndroid Build Coastguard Worker 
316*61046927SAndroid Build Coastguard Worker    if (!radv_image_use_fast_clear_for_image(device, image))
317*61046927SAndroid Build Coastguard Worker       return false;
318*61046927SAndroid Build Coastguard Worker 
319*61046927SAndroid Build Coastguard Worker    /* TODO: Fix storage images with DCC without DCC image stores.
320*61046927SAndroid Build Coastguard Worker     * Disabling it for now. */
321*61046927SAndroid Build Coastguard Worker    if ((image->vk.usage & VK_IMAGE_USAGE_STORAGE_BIT) && !radv_image_use_dcc_image_stores(device, image))
322*61046927SAndroid Build Coastguard Worker       return false;
323*61046927SAndroid Build Coastguard Worker 
324*61046927SAndroid Build Coastguard Worker    return true;
325*61046927SAndroid Build Coastguard Worker }
326*61046927SAndroid Build Coastguard Worker 
327*61046927SAndroid Build Coastguard Worker /*
328*61046927SAndroid Build Coastguard Worker  * Whether to enable image stores with DCC compression for this image. If
329*61046927SAndroid Build Coastguard Worker  * this function returns false the image subresource should be decompressed
330*61046927SAndroid Build Coastguard Worker  * before using it with image stores.
331*61046927SAndroid Build Coastguard Worker  *
332*61046927SAndroid Build Coastguard Worker  * Note that this can have mixed performance implications, see
333*61046927SAndroid Build Coastguard Worker  * https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6796#note_643299
334*61046927SAndroid Build Coastguard Worker  *
335*61046927SAndroid Build Coastguard Worker  * This function assumes the image uses DCC compression.
336*61046927SAndroid Build Coastguard Worker  */
337*61046927SAndroid Build Coastguard Worker bool
radv_image_use_dcc_image_stores(const struct radv_device * device,const struct radv_image * image)338*61046927SAndroid Build Coastguard Worker radv_image_use_dcc_image_stores(const struct radv_device *device, const struct radv_image *image)
339*61046927SAndroid Build Coastguard Worker {
340*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
341*61046927SAndroid Build Coastguard Worker 
342*61046927SAndroid Build Coastguard Worker    return ac_surface_supports_dcc_image_stores(pdev->info.gfx_level, &image->planes[0].surface);
343*61046927SAndroid Build Coastguard Worker }
344*61046927SAndroid Build Coastguard Worker 
345*61046927SAndroid Build Coastguard Worker /*
346*61046927SAndroid Build Coastguard Worker  * Whether to use a predicate to determine whether DCC is in a compressed
347*61046927SAndroid Build Coastguard Worker  * state. This can be used to avoid decompressing an image multiple times.
348*61046927SAndroid Build Coastguard Worker  */
349*61046927SAndroid Build Coastguard Worker bool
radv_image_use_dcc_predication(const struct radv_device * device,const struct radv_image * image)350*61046927SAndroid Build Coastguard Worker radv_image_use_dcc_predication(const struct radv_device *device, const struct radv_image *image)
351*61046927SAndroid Build Coastguard Worker {
352*61046927SAndroid Build Coastguard Worker    return radv_image_has_dcc(image) && !radv_image_use_dcc_image_stores(device, image);
353*61046927SAndroid Build Coastguard Worker }
354*61046927SAndroid Build Coastguard Worker 
355*61046927SAndroid Build Coastguard Worker static inline bool
radv_use_fmask_for_image(const struct radv_device * device,const struct radv_image * image)356*61046927SAndroid Build Coastguard Worker radv_use_fmask_for_image(const struct radv_device *device, const struct radv_image *image)
357*61046927SAndroid Build Coastguard Worker {
358*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
359*61046927SAndroid Build Coastguard Worker    const struct radv_instance *instance = radv_physical_device_instance(pdev);
360*61046927SAndroid Build Coastguard Worker 
361*61046927SAndroid Build Coastguard Worker    if (pdev->info.gfx_level == GFX9 && image->vk.array_layers > 1) {
362*61046927SAndroid Build Coastguard Worker       /* On GFX9, FMASK can be interleaved with layers and this isn't properly supported. */
363*61046927SAndroid Build Coastguard Worker       return false;
364*61046927SAndroid Build Coastguard Worker    }
365*61046927SAndroid Build Coastguard Worker 
366*61046927SAndroid Build Coastguard Worker    return pdev->use_fmask && image->vk.samples > 1 &&
367*61046927SAndroid Build Coastguard Worker           ((image->vk.usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) ||
368*61046927SAndroid Build Coastguard Worker            (instance->debug_flags & RADV_DEBUG_FORCE_COMPRESS));
369*61046927SAndroid Build Coastguard Worker }
370*61046927SAndroid Build Coastguard Worker 
371*61046927SAndroid Build Coastguard Worker static inline bool
radv_use_htile_for_image(const struct radv_device * device,const struct radv_image * image,const VkImageCreateInfo * pCreateInfo)372*61046927SAndroid Build Coastguard Worker radv_use_htile_for_image(const struct radv_device *device, const struct radv_image *image,
373*61046927SAndroid Build Coastguard Worker                          const VkImageCreateInfo *pCreateInfo)
374*61046927SAndroid Build Coastguard Worker {
375*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
376*61046927SAndroid Build Coastguard Worker    const struct radv_instance *instance = radv_physical_device_instance(pdev);
377*61046927SAndroid Build Coastguard Worker    const enum amd_gfx_level gfx_level = pdev->info.gfx_level;
378*61046927SAndroid Build Coastguard Worker 
379*61046927SAndroid Build Coastguard Worker    const VkImageCompressionControlEXT *compression =
380*61046927SAndroid Build Coastguard Worker       vk_find_struct_const(pCreateInfo->pNext, IMAGE_COMPRESSION_CONTROL_EXT);
381*61046927SAndroid Build Coastguard Worker 
382*61046927SAndroid Build Coastguard Worker    if (instance->debug_flags & RADV_DEBUG_NO_HIZ ||
383*61046927SAndroid Build Coastguard Worker        (compression && compression->flags == VK_IMAGE_COMPRESSION_DISABLED_EXT))
384*61046927SAndroid Build Coastguard Worker       return false;
385*61046927SAndroid Build Coastguard Worker 
386*61046927SAndroid Build Coastguard Worker    if (image->vk.usage & VK_IMAGE_USAGE_STORAGE_BIT)
387*61046927SAndroid Build Coastguard Worker       return false;
388*61046927SAndroid Build Coastguard Worker 
389*61046927SAndroid Build Coastguard Worker    /* TODO:
390*61046927SAndroid Build Coastguard Worker     * - Investigate about mips+layers.
391*61046927SAndroid Build Coastguard Worker     * - Enable on other gens.
392*61046927SAndroid Build Coastguard Worker     */
393*61046927SAndroid Build Coastguard Worker    bool use_htile_for_mips = image->vk.array_layers == 1 && pdev->info.gfx_level >= GFX10;
394*61046927SAndroid Build Coastguard Worker 
395*61046927SAndroid Build Coastguard Worker    /* Stencil texturing with HTILE doesn't work with mipmapping on Navi10-14. */
396*61046927SAndroid Build Coastguard Worker    if (pdev->info.gfx_level == GFX10 && image->vk.format == VK_FORMAT_D32_SFLOAT_S8_UINT && image->vk.mip_levels > 1)
397*61046927SAndroid Build Coastguard Worker       return false;
398*61046927SAndroid Build Coastguard Worker 
399*61046927SAndroid Build Coastguard Worker    /* Do not enable HTILE for very small images because it seems less performant but make sure it's
400*61046927SAndroid Build Coastguard Worker     * allowed with VRS attachments because we need HTILE on GFX10.3.
401*61046927SAndroid Build Coastguard Worker     */
402*61046927SAndroid Build Coastguard Worker    if (image->vk.extent.width * image->vk.extent.height < 8 * 8 &&
403*61046927SAndroid Build Coastguard Worker        !(instance->debug_flags & RADV_DEBUG_FORCE_COMPRESS) &&
404*61046927SAndroid Build Coastguard Worker        !(gfx_level == GFX10_3 && device->vk.enabled_features.attachmentFragmentShadingRate))
405*61046927SAndroid Build Coastguard Worker       return false;
406*61046927SAndroid Build Coastguard Worker 
407*61046927SAndroid Build Coastguard Worker    return (image->vk.mip_levels == 1 || use_htile_for_mips) && !image->shareable;
408*61046927SAndroid Build Coastguard Worker }
409*61046927SAndroid Build Coastguard Worker 
410*61046927SAndroid Build Coastguard Worker static bool
radv_use_tc_compat_cmask_for_image(struct radv_device * device,struct radv_image * image)411*61046927SAndroid Build Coastguard Worker radv_use_tc_compat_cmask_for_image(struct radv_device *device, struct radv_image *image)
412*61046927SAndroid Build Coastguard Worker {
413*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
414*61046927SAndroid Build Coastguard Worker    const struct radv_instance *instance = radv_physical_device_instance(pdev);
415*61046927SAndroid Build Coastguard Worker 
416*61046927SAndroid Build Coastguard Worker    /* TC-compat CMASK is only available for GFX8+. */
417*61046927SAndroid Build Coastguard Worker    if (pdev->info.gfx_level < GFX8)
418*61046927SAndroid Build Coastguard Worker       return false;
419*61046927SAndroid Build Coastguard Worker 
420*61046927SAndroid Build Coastguard Worker    /* GFX9 has issues when sample count is greater than 2 */
421*61046927SAndroid Build Coastguard Worker    if (pdev->info.gfx_level == GFX9 && image->vk.samples > 2)
422*61046927SAndroid Build Coastguard Worker       return false;
423*61046927SAndroid Build Coastguard Worker 
424*61046927SAndroid Build Coastguard Worker    if (instance->debug_flags & RADV_DEBUG_NO_TC_COMPAT_CMASK)
425*61046927SAndroid Build Coastguard Worker       return false;
426*61046927SAndroid Build Coastguard Worker 
427*61046927SAndroid Build Coastguard Worker    /* TC-compat CMASK with storage images is supported on GFX10+. */
428*61046927SAndroid Build Coastguard Worker    if ((image->vk.usage & VK_IMAGE_USAGE_STORAGE_BIT) && pdev->info.gfx_level < GFX10)
429*61046927SAndroid Build Coastguard Worker       return false;
430*61046927SAndroid Build Coastguard Worker 
431*61046927SAndroid Build Coastguard Worker    /* Do not enable TC-compatible if the image isn't readable by a shader
432*61046927SAndroid Build Coastguard Worker     * because no texture fetches will happen.
433*61046927SAndroid Build Coastguard Worker     */
434*61046927SAndroid Build Coastguard Worker    if (!(image->vk.usage &
435*61046927SAndroid Build Coastguard Worker          (VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)))
436*61046927SAndroid Build Coastguard Worker       return false;
437*61046927SAndroid Build Coastguard Worker 
438*61046927SAndroid Build Coastguard Worker    /* If the image doesn't have FMASK, it can't be fetchable. */
439*61046927SAndroid Build Coastguard Worker    if (!radv_image_has_fmask(image))
440*61046927SAndroid Build Coastguard Worker       return false;
441*61046927SAndroid Build Coastguard Worker 
442*61046927SAndroid Build Coastguard Worker    return true;
443*61046927SAndroid Build Coastguard Worker }
444*61046927SAndroid Build Coastguard Worker 
445*61046927SAndroid Build Coastguard Worker static uint32_t
radv_get_bo_metadata_word1(const struct radv_device * device)446*61046927SAndroid Build Coastguard Worker radv_get_bo_metadata_word1(const struct radv_device *device)
447*61046927SAndroid Build Coastguard Worker {
448*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
449*61046927SAndroid Build Coastguard Worker 
450*61046927SAndroid Build Coastguard Worker    return (ATI_VENDOR_ID << 16) | pdev->info.pci_id;
451*61046927SAndroid Build Coastguard Worker }
452*61046927SAndroid Build Coastguard Worker 
453*61046927SAndroid Build Coastguard Worker static bool
radv_is_valid_opaque_metadata(const struct radv_device * device,const struct radeon_bo_metadata * md)454*61046927SAndroid Build Coastguard Worker radv_is_valid_opaque_metadata(const struct radv_device *device, const struct radeon_bo_metadata *md)
455*61046927SAndroid Build Coastguard Worker {
456*61046927SAndroid Build Coastguard Worker    if (md->metadata[0] != 1 || md->metadata[1] != radv_get_bo_metadata_word1(device))
457*61046927SAndroid Build Coastguard Worker       return false;
458*61046927SAndroid Build Coastguard Worker 
459*61046927SAndroid Build Coastguard Worker    if (md->size_metadata < 40)
460*61046927SAndroid Build Coastguard Worker       return false;
461*61046927SAndroid Build Coastguard Worker 
462*61046927SAndroid Build Coastguard Worker    return true;
463*61046927SAndroid Build Coastguard Worker }
464*61046927SAndroid Build Coastguard Worker 
465*61046927SAndroid Build Coastguard Worker static void
radv_patch_surface_from_metadata(struct radv_device * device,struct radeon_surf * surface,const struct radeon_bo_metadata * md)466*61046927SAndroid Build Coastguard Worker radv_patch_surface_from_metadata(struct radv_device *device, struct radeon_surf *surface,
467*61046927SAndroid Build Coastguard Worker                                  const struct radeon_bo_metadata *md)
468*61046927SAndroid Build Coastguard Worker {
469*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
470*61046927SAndroid Build Coastguard Worker 
471*61046927SAndroid Build Coastguard Worker    surface->flags = RADEON_SURF_CLR(surface->flags, MODE);
472*61046927SAndroid Build Coastguard Worker 
473*61046927SAndroid Build Coastguard Worker    if (pdev->info.gfx_level >= GFX9) {
474*61046927SAndroid Build Coastguard Worker       if (md->u.gfx9.swizzle_mode > 0)
475*61046927SAndroid Build Coastguard Worker          surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
476*61046927SAndroid Build Coastguard Worker       else
477*61046927SAndroid Build Coastguard Worker          surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR_ALIGNED, MODE);
478*61046927SAndroid Build Coastguard Worker 
479*61046927SAndroid Build Coastguard Worker       surface->u.gfx9.swizzle_mode = md->u.gfx9.swizzle_mode;
480*61046927SAndroid Build Coastguard Worker    } else {
481*61046927SAndroid Build Coastguard Worker       surface->u.legacy.pipe_config = md->u.legacy.pipe_config;
482*61046927SAndroid Build Coastguard Worker       surface->u.legacy.bankw = md->u.legacy.bankw;
483*61046927SAndroid Build Coastguard Worker       surface->u.legacy.bankh = md->u.legacy.bankh;
484*61046927SAndroid Build Coastguard Worker       surface->u.legacy.tile_split = md->u.legacy.tile_split;
485*61046927SAndroid Build Coastguard Worker       surface->u.legacy.mtilea = md->u.legacy.mtilea;
486*61046927SAndroid Build Coastguard Worker       surface->u.legacy.num_banks = md->u.legacy.num_banks;
487*61046927SAndroid Build Coastguard Worker 
488*61046927SAndroid Build Coastguard Worker       if (md->u.legacy.macrotile == RADEON_LAYOUT_TILED)
489*61046927SAndroid Build Coastguard Worker          surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
490*61046927SAndroid Build Coastguard Worker       else if (md->u.legacy.microtile == RADEON_LAYOUT_TILED)
491*61046927SAndroid Build Coastguard Worker          surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
492*61046927SAndroid Build Coastguard Worker       else
493*61046927SAndroid Build Coastguard Worker          surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR_ALIGNED, MODE);
494*61046927SAndroid Build Coastguard Worker    }
495*61046927SAndroid Build Coastguard Worker }
496*61046927SAndroid Build Coastguard Worker 
497*61046927SAndroid Build Coastguard Worker static VkResult
radv_patch_image_dimensions(struct radv_device * device,struct radv_image * image,const struct radv_image_create_info * create_info,struct ac_surf_info * image_info)498*61046927SAndroid Build Coastguard Worker radv_patch_image_dimensions(struct radv_device *device, struct radv_image *image,
499*61046927SAndroid Build Coastguard Worker                             const struct radv_image_create_info *create_info, struct ac_surf_info *image_info)
500*61046927SAndroid Build Coastguard Worker {
501*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
502*61046927SAndroid Build Coastguard Worker    unsigned width = image->vk.extent.width;
503*61046927SAndroid Build Coastguard Worker    unsigned height = image->vk.extent.height;
504*61046927SAndroid Build Coastguard Worker 
505*61046927SAndroid Build Coastguard Worker    /*
506*61046927SAndroid Build Coastguard Worker     * minigbm sometimes allocates bigger images which is going to result in
507*61046927SAndroid Build Coastguard Worker     * weird strides and other properties. Lets be lenient where possible and
508*61046927SAndroid Build Coastguard Worker     * fail it on GFX10 (as we cannot cope there).
509*61046927SAndroid Build Coastguard Worker     *
510*61046927SAndroid Build Coastguard Worker     * Example hack: https://chromium-review.googlesource.com/c/chromiumos/platform/minigbm/+/1457777/
511*61046927SAndroid Build Coastguard Worker     */
512*61046927SAndroid Build Coastguard Worker    if (create_info->bo_metadata && radv_is_valid_opaque_metadata(device, create_info->bo_metadata)) {
513*61046927SAndroid Build Coastguard Worker       const struct radeon_bo_metadata *md = create_info->bo_metadata;
514*61046927SAndroid Build Coastguard Worker 
515*61046927SAndroid Build Coastguard Worker       if (pdev->info.gfx_level >= GFX10) {
516*61046927SAndroid Build Coastguard Worker          width = G_00A004_WIDTH_LO(md->metadata[3]) + (G_00A008_WIDTH_HI(md->metadata[4]) << 2) + 1;
517*61046927SAndroid Build Coastguard Worker          height = G_00A008_HEIGHT(md->metadata[4]) + 1;
518*61046927SAndroid Build Coastguard Worker       } else {
519*61046927SAndroid Build Coastguard Worker          width = G_008F18_WIDTH(md->metadata[4]) + 1;
520*61046927SAndroid Build Coastguard Worker          height = G_008F18_HEIGHT(md->metadata[4]) + 1;
521*61046927SAndroid Build Coastguard Worker       }
522*61046927SAndroid Build Coastguard Worker    }
523*61046927SAndroid Build Coastguard Worker 
524*61046927SAndroid Build Coastguard Worker    if (image->vk.extent.width == width && image->vk.extent.height == height)
525*61046927SAndroid Build Coastguard Worker       return VK_SUCCESS;
526*61046927SAndroid Build Coastguard Worker 
527*61046927SAndroid Build Coastguard Worker    if (width < image->vk.extent.width || height < image->vk.extent.height) {
528*61046927SAndroid Build Coastguard Worker       fprintf(stderr,
529*61046927SAndroid Build Coastguard Worker               "The imported image has smaller dimensions than the internal\n"
530*61046927SAndroid Build Coastguard Worker               "dimensions. Using it is going to fail badly, so we reject\n"
531*61046927SAndroid Build Coastguard Worker               "this import.\n"
532*61046927SAndroid Build Coastguard Worker               "(internal dimensions: %d x %d, external dimensions: %d x %d)\n",
533*61046927SAndroid Build Coastguard Worker               image->vk.extent.width, image->vk.extent.height, width, height);
534*61046927SAndroid Build Coastguard Worker       return VK_ERROR_INVALID_EXTERNAL_HANDLE;
535*61046927SAndroid Build Coastguard Worker    } else if (pdev->info.gfx_level >= GFX10) {
536*61046927SAndroid Build Coastguard Worker       fprintf(stderr,
537*61046927SAndroid Build Coastguard Worker               "Tried to import an image with inconsistent width on GFX10.\n"
538*61046927SAndroid Build Coastguard Worker               "As GFX10 has no separate stride fields we cannot cope with\n"
539*61046927SAndroid Build Coastguard Worker               "an inconsistency in width and will fail this import.\n"
540*61046927SAndroid Build Coastguard Worker               "(internal dimensions: %d x %d, external dimensions: %d x %d)\n",
541*61046927SAndroid Build Coastguard Worker               image->vk.extent.width, image->vk.extent.height, width, height);
542*61046927SAndroid Build Coastguard Worker       return VK_ERROR_INVALID_EXTERNAL_HANDLE;
543*61046927SAndroid Build Coastguard Worker    } else {
544*61046927SAndroid Build Coastguard Worker       fprintf(stderr,
545*61046927SAndroid Build Coastguard Worker               "Tried to import an image with inconsistent width on pre-GFX10.\n"
546*61046927SAndroid Build Coastguard Worker               "As GFX10 has no separate stride fields we cannot cope with\n"
547*61046927SAndroid Build Coastguard Worker               "an inconsistency and would fail on GFX10.\n"
548*61046927SAndroid Build Coastguard Worker               "(internal dimensions: %d x %d, external dimensions: %d x %d)\n",
549*61046927SAndroid Build Coastguard Worker               image->vk.extent.width, image->vk.extent.height, width, height);
550*61046927SAndroid Build Coastguard Worker    }
551*61046927SAndroid Build Coastguard Worker    image_info->width = width;
552*61046927SAndroid Build Coastguard Worker    image_info->height = height;
553*61046927SAndroid Build Coastguard Worker 
554*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
555*61046927SAndroid Build Coastguard Worker }
556*61046927SAndroid Build Coastguard Worker 
557*61046927SAndroid Build Coastguard Worker static VkResult
radv_patch_image_from_extra_info(struct radv_device * device,struct radv_image * image,const struct radv_image_create_info * create_info,struct ac_surf_info * image_info)558*61046927SAndroid Build Coastguard Worker radv_patch_image_from_extra_info(struct radv_device *device, struct radv_image *image,
559*61046927SAndroid Build Coastguard Worker                                  const struct radv_image_create_info *create_info, struct ac_surf_info *image_info)
560*61046927SAndroid Build Coastguard Worker {
561*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
562*61046927SAndroid Build Coastguard Worker    const struct radv_instance *instance = radv_physical_device_instance(pdev);
563*61046927SAndroid Build Coastguard Worker 
564*61046927SAndroid Build Coastguard Worker    VkResult result = radv_patch_image_dimensions(device, image, create_info, image_info);
565*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
566*61046927SAndroid Build Coastguard Worker       return result;
567*61046927SAndroid Build Coastguard Worker 
568*61046927SAndroid Build Coastguard Worker    for (unsigned plane = 0; plane < image->plane_count; ++plane) {
569*61046927SAndroid Build Coastguard Worker       if (create_info->bo_metadata) {
570*61046927SAndroid Build Coastguard Worker          radv_patch_surface_from_metadata(device, &image->planes[plane].surface, create_info->bo_metadata);
571*61046927SAndroid Build Coastguard Worker       }
572*61046927SAndroid Build Coastguard Worker 
573*61046927SAndroid Build Coastguard Worker       if (radv_surface_has_scanout(device, create_info)) {
574*61046927SAndroid Build Coastguard Worker          image->planes[plane].surface.flags |= RADEON_SURF_SCANOUT;
575*61046927SAndroid Build Coastguard Worker          if (instance->debug_flags & RADV_DEBUG_NO_DISPLAY_DCC)
576*61046927SAndroid Build Coastguard Worker             image->planes[plane].surface.flags |= RADEON_SURF_DISABLE_DCC;
577*61046927SAndroid Build Coastguard Worker 
578*61046927SAndroid Build Coastguard Worker          image_info->surf_index = NULL;
579*61046927SAndroid Build Coastguard Worker       }
580*61046927SAndroid Build Coastguard Worker 
581*61046927SAndroid Build Coastguard Worker       if (create_info->prime_blit_src && !pdev->info.sdma_supports_compression) {
582*61046927SAndroid Build Coastguard Worker          /* Older SDMA hw can't handle DCC */
583*61046927SAndroid Build Coastguard Worker          image->planes[plane].surface.flags |= RADEON_SURF_DISABLE_DCC;
584*61046927SAndroid Build Coastguard Worker       }
585*61046927SAndroid Build Coastguard Worker    }
586*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
587*61046927SAndroid Build Coastguard Worker }
588*61046927SAndroid Build Coastguard Worker 
589*61046927SAndroid Build Coastguard Worker static VkFormat
radv_image_get_plane_format(const struct radv_physical_device * pdev,const struct radv_image * image,unsigned plane)590*61046927SAndroid Build Coastguard Worker radv_image_get_plane_format(const struct radv_physical_device *pdev, const struct radv_image *image, unsigned plane)
591*61046927SAndroid Build Coastguard Worker {
592*61046927SAndroid Build Coastguard Worker    if (radv_is_format_emulated(pdev, image->vk.format)) {
593*61046927SAndroid Build Coastguard Worker       if (plane == 0)
594*61046927SAndroid Build Coastguard Worker          return image->vk.format;
595*61046927SAndroid Build Coastguard Worker       if (vk_format_description(image->vk.format)->layout == UTIL_FORMAT_LAYOUT_ASTC)
596*61046927SAndroid Build Coastguard Worker          return vk_texcompress_astc_emulation_format(image->vk.format);
597*61046927SAndroid Build Coastguard Worker       else
598*61046927SAndroid Build Coastguard Worker          return vk_texcompress_etc2_emulation_format(image->vk.format);
599*61046927SAndroid Build Coastguard Worker    }
600*61046927SAndroid Build Coastguard Worker 
601*61046927SAndroid Build Coastguard Worker    return vk_format_get_plane_format(image->vk.format, plane);
602*61046927SAndroid Build Coastguard Worker }
603*61046927SAndroid Build Coastguard Worker 
604*61046927SAndroid Build Coastguard Worker static uint64_t
radv_get_surface_flags(struct radv_device * device,struct radv_image * image,unsigned plane_id,const VkImageCreateInfo * pCreateInfo,VkFormat image_format)605*61046927SAndroid Build Coastguard Worker radv_get_surface_flags(struct radv_device *device, struct radv_image *image, unsigned plane_id,
606*61046927SAndroid Build Coastguard Worker                        const VkImageCreateInfo *pCreateInfo, VkFormat image_format)
607*61046927SAndroid Build Coastguard Worker {
608*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
609*61046927SAndroid Build Coastguard Worker    const struct radv_instance *instance = radv_physical_device_instance(pdev);
610*61046927SAndroid Build Coastguard Worker    uint64_t flags;
611*61046927SAndroid Build Coastguard Worker    unsigned array_mode = radv_choose_tiling(device, pCreateInfo, image_format);
612*61046927SAndroid Build Coastguard Worker    VkFormat format = radv_image_get_plane_format(pdev, image, plane_id);
613*61046927SAndroid Build Coastguard Worker    const struct util_format_description *desc = vk_format_description(format);
614*61046927SAndroid Build Coastguard Worker    const VkImageAlignmentControlCreateInfoMESA *alignment =
615*61046927SAndroid Build Coastguard Worker          vk_find_struct_const(pCreateInfo->pNext, IMAGE_ALIGNMENT_CONTROL_CREATE_INFO_MESA);
616*61046927SAndroid Build Coastguard Worker    bool is_depth, is_stencil;
617*61046927SAndroid Build Coastguard Worker 
618*61046927SAndroid Build Coastguard Worker    is_depth = util_format_has_depth(desc);
619*61046927SAndroid Build Coastguard Worker    is_stencil = util_format_has_stencil(desc);
620*61046927SAndroid Build Coastguard Worker 
621*61046927SAndroid Build Coastguard Worker    flags = RADEON_SURF_SET(array_mode, MODE);
622*61046927SAndroid Build Coastguard Worker 
623*61046927SAndroid Build Coastguard Worker    switch (pCreateInfo->imageType) {
624*61046927SAndroid Build Coastguard Worker    case VK_IMAGE_TYPE_1D:
625*61046927SAndroid Build Coastguard Worker       if (pCreateInfo->arrayLayers > 1)
626*61046927SAndroid Build Coastguard Worker          flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_1D_ARRAY, TYPE);
627*61046927SAndroid Build Coastguard Worker       else
628*61046927SAndroid Build Coastguard Worker          flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_1D, TYPE);
629*61046927SAndroid Build Coastguard Worker       break;
630*61046927SAndroid Build Coastguard Worker    case VK_IMAGE_TYPE_2D:
631*61046927SAndroid Build Coastguard Worker       if (pCreateInfo->arrayLayers > 1)
632*61046927SAndroid Build Coastguard Worker          flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D_ARRAY, TYPE);
633*61046927SAndroid Build Coastguard Worker       else
634*61046927SAndroid Build Coastguard Worker          flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE);
635*61046927SAndroid Build Coastguard Worker       break;
636*61046927SAndroid Build Coastguard Worker    case VK_IMAGE_TYPE_3D:
637*61046927SAndroid Build Coastguard Worker       flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_3D, TYPE);
638*61046927SAndroid Build Coastguard Worker       break;
639*61046927SAndroid Build Coastguard Worker    default:
640*61046927SAndroid Build Coastguard Worker       unreachable("unhandled image type");
641*61046927SAndroid Build Coastguard Worker    }
642*61046927SAndroid Build Coastguard Worker 
643*61046927SAndroid Build Coastguard Worker    /* Required for clearing/initializing a specific layer on GFX8. */
644*61046927SAndroid Build Coastguard Worker    flags |= RADEON_SURF_CONTIGUOUS_DCC_LAYERS;
645*61046927SAndroid Build Coastguard Worker 
646*61046927SAndroid Build Coastguard Worker    if (is_depth) {
647*61046927SAndroid Build Coastguard Worker       flags |= RADEON_SURF_ZBUFFER;
648*61046927SAndroid Build Coastguard Worker 
649*61046927SAndroid Build Coastguard Worker       if (is_depth && is_stencil && pdev->info.gfx_level <= GFX8) {
650*61046927SAndroid Build Coastguard Worker          if (!(pCreateInfo->usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT))
651*61046927SAndroid Build Coastguard Worker             flags |= RADEON_SURF_NO_RENDER_TARGET;
652*61046927SAndroid Build Coastguard Worker 
653*61046927SAndroid Build Coastguard Worker          /* RADV doesn't support stencil pitch adjustment. As a result there are some spec gaps that
654*61046927SAndroid Build Coastguard Worker           * are not covered by CTS.
655*61046927SAndroid Build Coastguard Worker           *
656*61046927SAndroid Build Coastguard Worker           * For D+S images with pitch constraints due to rendertarget usage it can happen that
657*61046927SAndroid Build Coastguard Worker           * sampling from mipmaps beyond the base level of the descriptor is broken as the pitch
658*61046927SAndroid Build Coastguard Worker           * adjustment can't be applied to anything beyond the first level.
659*61046927SAndroid Build Coastguard Worker           */
660*61046927SAndroid Build Coastguard Worker          flags |= RADEON_SURF_NO_STENCIL_ADJUST;
661*61046927SAndroid Build Coastguard Worker       }
662*61046927SAndroid Build Coastguard Worker 
663*61046927SAndroid Build Coastguard Worker       if (radv_use_htile_for_image(device, image, pCreateInfo) && !(flags & RADEON_SURF_NO_RENDER_TARGET)) {
664*61046927SAndroid Build Coastguard Worker          if (radv_use_tc_compat_htile_for_image(device, pCreateInfo, image_format))
665*61046927SAndroid Build Coastguard Worker             flags |= RADEON_SURF_TC_COMPATIBLE_HTILE;
666*61046927SAndroid Build Coastguard Worker       } else {
667*61046927SAndroid Build Coastguard Worker          flags |= RADEON_SURF_NO_HTILE;
668*61046927SAndroid Build Coastguard Worker       }
669*61046927SAndroid Build Coastguard Worker    }
670*61046927SAndroid Build Coastguard Worker 
671*61046927SAndroid Build Coastguard Worker    if (is_stencil)
672*61046927SAndroid Build Coastguard Worker       flags |= RADEON_SURF_SBUFFER;
673*61046927SAndroid Build Coastguard Worker 
674*61046927SAndroid Build Coastguard Worker    if (pdev->info.gfx_level >= GFX9 && pCreateInfo->imageType == VK_IMAGE_TYPE_3D &&
675*61046927SAndroid Build Coastguard Worker        vk_format_get_blocksizebits(image_format) == 128 && vk_format_is_compressed(image_format))
676*61046927SAndroid Build Coastguard Worker       flags |= RADEON_SURF_NO_RENDER_TARGET;
677*61046927SAndroid Build Coastguard Worker 
678*61046927SAndroid Build Coastguard Worker    if (!radv_use_dcc_for_image_early(device, image, pCreateInfo, image_format, &image->dcc_sign_reinterpret))
679*61046927SAndroid Build Coastguard Worker       flags |= RADEON_SURF_DISABLE_DCC;
680*61046927SAndroid Build Coastguard Worker 
681*61046927SAndroid Build Coastguard Worker    if (!radv_use_fmask_for_image(device, image))
682*61046927SAndroid Build Coastguard Worker       flags |= RADEON_SURF_NO_FMASK;
683*61046927SAndroid Build Coastguard Worker 
684*61046927SAndroid Build Coastguard Worker    if (pCreateInfo->flags & VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT) {
685*61046927SAndroid Build Coastguard Worker       flags |= RADEON_SURF_PRT | RADEON_SURF_NO_FMASK | RADEON_SURF_NO_HTILE | RADEON_SURF_DISABLE_DCC;
686*61046927SAndroid Build Coastguard Worker    }
687*61046927SAndroid Build Coastguard Worker 
688*61046927SAndroid Build Coastguard Worker    if (image->queue_family_mask & BITFIELD_BIT(RADV_QUEUE_TRANSFER)) {
689*61046927SAndroid Build Coastguard Worker       if (!pdev->info.sdma_supports_compression)
690*61046927SAndroid Build Coastguard Worker          flags |= RADEON_SURF_DISABLE_DCC | RADEON_SURF_NO_HTILE;
691*61046927SAndroid Build Coastguard Worker    }
692*61046927SAndroid Build Coastguard Worker 
693*61046927SAndroid Build Coastguard Worker    /* Disable DCC for VRS rate images because the hw can't handle compression. */
694*61046927SAndroid Build Coastguard Worker    if (pCreateInfo->usage & VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR)
695*61046927SAndroid Build Coastguard Worker       flags |= RADEON_SURF_VRS_RATE | RADEON_SURF_DISABLE_DCC;
696*61046927SAndroid Build Coastguard Worker    if (!(pCreateInfo->usage & (VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT)))
697*61046927SAndroid Build Coastguard Worker       flags |= RADEON_SURF_NO_TEXTURE;
698*61046927SAndroid Build Coastguard Worker 
699*61046927SAndroid Build Coastguard Worker    if (alignment && alignment->maximumRequestedAlignment && !(instance->debug_flags & RADV_DEBUG_FORCE_COMPRESS)) {
700*61046927SAndroid Build Coastguard Worker       bool is_4k_capable;
701*61046927SAndroid Build Coastguard Worker 
702*61046927SAndroid Build Coastguard Worker       if (!vk_format_is_depth_or_stencil(image_format)) {
703*61046927SAndroid Build Coastguard Worker          is_4k_capable =
704*61046927SAndroid Build Coastguard Worker                !(pCreateInfo->usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) && (flags & RADEON_SURF_DISABLE_DCC) &&
705*61046927SAndroid Build Coastguard Worker                (flags & RADEON_SURF_NO_FMASK);
706*61046927SAndroid Build Coastguard Worker       } else {
707*61046927SAndroid Build Coastguard Worker          /* Depth-stencil format without DEPTH_STENCIL usage does not work either. */
708*61046927SAndroid Build Coastguard Worker          is_4k_capable = false;
709*61046927SAndroid Build Coastguard Worker       }
710*61046927SAndroid Build Coastguard Worker 
711*61046927SAndroid Build Coastguard Worker       if (is_4k_capable && alignment->maximumRequestedAlignment <= 4096)
712*61046927SAndroid Build Coastguard Worker          flags |= RADEON_SURF_PREFER_4K_ALIGNMENT;
713*61046927SAndroid Build Coastguard Worker       if (alignment->maximumRequestedAlignment <= 64 * 1024)
714*61046927SAndroid Build Coastguard Worker          flags |= RADEON_SURF_PREFER_64K_ALIGNMENT;
715*61046927SAndroid Build Coastguard Worker    }
716*61046927SAndroid Build Coastguard Worker 
717*61046927SAndroid Build Coastguard Worker    return flags;
718*61046927SAndroid Build Coastguard Worker }
719*61046927SAndroid Build Coastguard Worker 
720*61046927SAndroid Build Coastguard Worker void
radv_compose_swizzle(const struct util_format_description * desc,const VkComponentMapping * mapping,enum pipe_swizzle swizzle[4])721*61046927SAndroid Build Coastguard Worker radv_compose_swizzle(const struct util_format_description *desc, const VkComponentMapping *mapping,
722*61046927SAndroid Build Coastguard Worker                      enum pipe_swizzle swizzle[4])
723*61046927SAndroid Build Coastguard Worker {
724*61046927SAndroid Build Coastguard Worker    if (desc->format == PIPE_FORMAT_R64_UINT || desc->format == PIPE_FORMAT_R64_SINT) {
725*61046927SAndroid Build Coastguard Worker       /* 64-bit formats only support storage images and storage images
726*61046927SAndroid Build Coastguard Worker        * require identity component mappings. We use 32-bit
727*61046927SAndroid Build Coastguard Worker        * instructions to access 64-bit images, so we need a special
728*61046927SAndroid Build Coastguard Worker        * case here.
729*61046927SAndroid Build Coastguard Worker        *
730*61046927SAndroid Build Coastguard Worker        * The zw components are 1,0 so that they can be easily be used
731*61046927SAndroid Build Coastguard Worker        * by loads to create the w component, which has to be 0 for
732*61046927SAndroid Build Coastguard Worker        * NULL descriptors.
733*61046927SAndroid Build Coastguard Worker        */
734*61046927SAndroid Build Coastguard Worker       swizzle[0] = PIPE_SWIZZLE_X;
735*61046927SAndroid Build Coastguard Worker       swizzle[1] = PIPE_SWIZZLE_Y;
736*61046927SAndroid Build Coastguard Worker       swizzle[2] = PIPE_SWIZZLE_1;
737*61046927SAndroid Build Coastguard Worker       swizzle[3] = PIPE_SWIZZLE_0;
738*61046927SAndroid Build Coastguard Worker    } else if (!mapping) {
739*61046927SAndroid Build Coastguard Worker       for (unsigned i = 0; i < 4; i++)
740*61046927SAndroid Build Coastguard Worker          swizzle[i] = desc->swizzle[i];
741*61046927SAndroid Build Coastguard Worker    } else if (desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) {
742*61046927SAndroid Build Coastguard Worker       const unsigned char swizzle_xxxx[4] = {PIPE_SWIZZLE_X, PIPE_SWIZZLE_0, PIPE_SWIZZLE_0, PIPE_SWIZZLE_1};
743*61046927SAndroid Build Coastguard Worker       vk_format_compose_swizzles(mapping, swizzle_xxxx, swizzle);
744*61046927SAndroid Build Coastguard Worker    } else {
745*61046927SAndroid Build Coastguard Worker       vk_format_compose_swizzles(mapping, desc->swizzle, swizzle);
746*61046927SAndroid Build Coastguard Worker    }
747*61046927SAndroid Build Coastguard Worker }
748*61046927SAndroid Build Coastguard Worker 
749*61046927SAndroid Build Coastguard Worker static void
radv_query_opaque_metadata(struct radv_device * device,struct radv_image * image,unsigned plane_id,struct radeon_bo_metadata * md)750*61046927SAndroid Build Coastguard Worker radv_query_opaque_metadata(struct radv_device *device, struct radv_image *image, unsigned plane_id,
751*61046927SAndroid Build Coastguard Worker                            struct radeon_bo_metadata *md)
752*61046927SAndroid Build Coastguard Worker {
753*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
754*61046927SAndroid Build Coastguard Worker    const struct radv_instance *instance = radv_physical_device_instance(pdev);
755*61046927SAndroid Build Coastguard Worker    static const VkComponentMapping fixedmapping;
756*61046927SAndroid Build Coastguard Worker    const VkFormat plane_format = radv_image_get_plane_format(pdev, image, plane_id);
757*61046927SAndroid Build Coastguard Worker    const unsigned plane_width = vk_format_get_plane_width(image->vk.format, plane_id, image->vk.extent.width);
758*61046927SAndroid Build Coastguard Worker    const unsigned plane_height = vk_format_get_plane_height(image->vk.format, plane_id, image->vk.extent.height);
759*61046927SAndroid Build Coastguard Worker    struct radeon_surf *surface = &image->planes[plane_id].surface;
760*61046927SAndroid Build Coastguard Worker    const struct legacy_surf_level *base_level_info = pdev->info.gfx_level <= GFX8 ? &surface->u.legacy.level[0] : NULL;
761*61046927SAndroid Build Coastguard Worker    uint32_t desc[8];
762*61046927SAndroid Build Coastguard Worker 
763*61046927SAndroid Build Coastguard Worker    radv_make_texture_descriptor(device, image, false, (VkImageViewType)image->vk.image_type, plane_format,
764*61046927SAndroid Build Coastguard Worker                                 &fixedmapping, 0, image->vk.mip_levels - 1, 0, image->vk.array_layers - 1, plane_width,
765*61046927SAndroid Build Coastguard Worker                                 plane_height, image->vk.extent.depth, 0.0f, desc, NULL, 0, NULL, NULL);
766*61046927SAndroid Build Coastguard Worker 
767*61046927SAndroid Build Coastguard Worker    radv_set_mutable_tex_desc_fields(device, image, base_level_info, plane_id, 0, 0, surface->blk_w, false, false, false,
768*61046927SAndroid Build Coastguard Worker                                     false, desc, NULL);
769*61046927SAndroid Build Coastguard Worker 
770*61046927SAndroid Build Coastguard Worker    ac_surface_compute_umd_metadata(&pdev->info, surface, image->vk.mip_levels, desc, &md->size_metadata, md->metadata,
771*61046927SAndroid Build Coastguard Worker                                    instance->debug_flags & RADV_DEBUG_EXTRA_MD);
772*61046927SAndroid Build Coastguard Worker }
773*61046927SAndroid Build Coastguard Worker 
774*61046927SAndroid Build Coastguard Worker void
radv_init_metadata(struct radv_device * device,struct radv_image * image,struct radeon_bo_metadata * metadata)775*61046927SAndroid Build Coastguard Worker radv_init_metadata(struct radv_device *device, struct radv_image *image, struct radeon_bo_metadata *metadata)
776*61046927SAndroid Build Coastguard Worker {
777*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
778*61046927SAndroid Build Coastguard Worker 
779*61046927SAndroid Build Coastguard Worker    /* use plane 0, even when there are multiple planes, to follow radeonsi */
780*61046927SAndroid Build Coastguard Worker    const unsigned plane_id = 0;
781*61046927SAndroid Build Coastguard Worker    struct radeon_surf *surface = &image->planes[plane_id].surface;
782*61046927SAndroid Build Coastguard Worker 
783*61046927SAndroid Build Coastguard Worker    memset(metadata, 0, sizeof(*metadata));
784*61046927SAndroid Build Coastguard Worker 
785*61046927SAndroid Build Coastguard Worker    if (pdev->info.gfx_level >= GFX9) {
786*61046927SAndroid Build Coastguard Worker       uint64_t dcc_offset =
787*61046927SAndroid Build Coastguard Worker          image->bindings[0].offset + (surface->display_dcc_offset ? surface->display_dcc_offset : surface->meta_offset);
788*61046927SAndroid Build Coastguard Worker       metadata->u.gfx9.swizzle_mode = surface->u.gfx9.swizzle_mode;
789*61046927SAndroid Build Coastguard Worker       metadata->u.gfx9.dcc_offset_256b = dcc_offset >> 8;
790*61046927SAndroid Build Coastguard Worker       metadata->u.gfx9.dcc_pitch_max = surface->u.gfx9.color.display_dcc_pitch_max;
791*61046927SAndroid Build Coastguard Worker       metadata->u.gfx9.dcc_independent_64b_blocks = surface->u.gfx9.color.dcc.independent_64B_blocks;
792*61046927SAndroid Build Coastguard Worker       metadata->u.gfx9.dcc_independent_128b_blocks = surface->u.gfx9.color.dcc.independent_128B_blocks;
793*61046927SAndroid Build Coastguard Worker       metadata->u.gfx9.dcc_max_compressed_block_size = surface->u.gfx9.color.dcc.max_compressed_block_size;
794*61046927SAndroid Build Coastguard Worker       metadata->u.gfx9.scanout = (surface->flags & RADEON_SURF_SCANOUT) != 0;
795*61046927SAndroid Build Coastguard Worker    } else {
796*61046927SAndroid Build Coastguard Worker       metadata->u.legacy.microtile =
797*61046927SAndroid Build Coastguard Worker          surface->u.legacy.level[0].mode >= RADEON_SURF_MODE_1D ? RADEON_LAYOUT_TILED : RADEON_LAYOUT_LINEAR;
798*61046927SAndroid Build Coastguard Worker       metadata->u.legacy.macrotile =
799*61046927SAndroid Build Coastguard Worker          surface->u.legacy.level[0].mode >= RADEON_SURF_MODE_2D ? RADEON_LAYOUT_TILED : RADEON_LAYOUT_LINEAR;
800*61046927SAndroid Build Coastguard Worker       metadata->u.legacy.pipe_config = surface->u.legacy.pipe_config;
801*61046927SAndroid Build Coastguard Worker       metadata->u.legacy.bankw = surface->u.legacy.bankw;
802*61046927SAndroid Build Coastguard Worker       metadata->u.legacy.bankh = surface->u.legacy.bankh;
803*61046927SAndroid Build Coastguard Worker       metadata->u.legacy.tile_split = surface->u.legacy.tile_split;
804*61046927SAndroid Build Coastguard Worker       metadata->u.legacy.mtilea = surface->u.legacy.mtilea;
805*61046927SAndroid Build Coastguard Worker       metadata->u.legacy.num_banks = surface->u.legacy.num_banks;
806*61046927SAndroid Build Coastguard Worker       metadata->u.legacy.stride = surface->u.legacy.level[0].nblk_x * surface->bpe;
807*61046927SAndroid Build Coastguard Worker       metadata->u.legacy.scanout = (surface->flags & RADEON_SURF_SCANOUT) != 0;
808*61046927SAndroid Build Coastguard Worker    }
809*61046927SAndroid Build Coastguard Worker    radv_query_opaque_metadata(device, image, plane_id, metadata);
810*61046927SAndroid Build Coastguard Worker }
811*61046927SAndroid Build Coastguard Worker 
812*61046927SAndroid Build Coastguard Worker void
radv_image_override_offset_stride(struct radv_device * device,struct radv_image * image,uint64_t offset,uint32_t stride)813*61046927SAndroid Build Coastguard Worker radv_image_override_offset_stride(struct radv_device *device, struct radv_image *image, uint64_t offset,
814*61046927SAndroid Build Coastguard Worker                                   uint32_t stride)
815*61046927SAndroid Build Coastguard Worker {
816*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
817*61046927SAndroid Build Coastguard Worker    ac_surface_override_offset_stride(&pdev->info, &image->planes[0].surface, image->vk.array_layers,
818*61046927SAndroid Build Coastguard Worker                                      image->vk.mip_levels, offset, stride);
819*61046927SAndroid Build Coastguard Worker }
820*61046927SAndroid Build Coastguard Worker 
821*61046927SAndroid Build Coastguard Worker static void
radv_image_alloc_single_sample_cmask(const struct radv_device * device,const struct radv_image * image,struct radeon_surf * surf)822*61046927SAndroid Build Coastguard Worker radv_image_alloc_single_sample_cmask(const struct radv_device *device, const struct radv_image *image,
823*61046927SAndroid Build Coastguard Worker                                      struct radeon_surf *surf)
824*61046927SAndroid Build Coastguard Worker {
825*61046927SAndroid Build Coastguard Worker    if (!surf->cmask_size || surf->cmask_offset || surf->bpe > 8 || image->vk.mip_levels > 1 ||
826*61046927SAndroid Build Coastguard Worker        image->vk.extent.depth > 1 || radv_image_has_dcc(image) || !radv_image_use_fast_clear_for_image(device, image) ||
827*61046927SAndroid Build Coastguard Worker        (image->vk.create_flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT))
828*61046927SAndroid Build Coastguard Worker       return;
829*61046927SAndroid Build Coastguard Worker 
830*61046927SAndroid Build Coastguard Worker    assert(image->vk.samples == 1);
831*61046927SAndroid Build Coastguard Worker 
832*61046927SAndroid Build Coastguard Worker    surf->cmask_offset = align64(surf->total_size, 1ull << surf->cmask_alignment_log2);
833*61046927SAndroid Build Coastguard Worker    surf->total_size = surf->cmask_offset + surf->cmask_size;
834*61046927SAndroid Build Coastguard Worker    surf->alignment_log2 = MAX2(surf->alignment_log2, surf->cmask_alignment_log2);
835*61046927SAndroid Build Coastguard Worker }
836*61046927SAndroid Build Coastguard Worker 
837*61046927SAndroid Build Coastguard Worker static void
radv_image_alloc_values(const struct radv_device * device,struct radv_image * image)838*61046927SAndroid Build Coastguard Worker radv_image_alloc_values(const struct radv_device *device, struct radv_image *image)
839*61046927SAndroid Build Coastguard Worker {
840*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
841*61046927SAndroid Build Coastguard Worker 
842*61046927SAndroid Build Coastguard Worker    /* images with modifiers can be potentially imported */
843*61046927SAndroid Build Coastguard Worker    if (image->vk.tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT)
844*61046927SAndroid Build Coastguard Worker       return;
845*61046927SAndroid Build Coastguard Worker 
846*61046927SAndroid Build Coastguard Worker    if (radv_image_has_cmask(image) || (radv_image_has_dcc(image) && !image->support_comp_to_single)) {
847*61046927SAndroid Build Coastguard Worker       image->fce_pred_offset = image->size;
848*61046927SAndroid Build Coastguard Worker       image->size += 8 * image->vk.mip_levels;
849*61046927SAndroid Build Coastguard Worker    }
850*61046927SAndroid Build Coastguard Worker 
851*61046927SAndroid Build Coastguard Worker    if (radv_image_use_dcc_predication(device, image)) {
852*61046927SAndroid Build Coastguard Worker       image->dcc_pred_offset = image->size;
853*61046927SAndroid Build Coastguard Worker       image->size += 8 * image->vk.mip_levels;
854*61046927SAndroid Build Coastguard Worker    }
855*61046927SAndroid Build Coastguard Worker 
856*61046927SAndroid Build Coastguard Worker    if ((radv_image_has_dcc(image) && !image->support_comp_to_single) || radv_image_has_cmask(image) ||
857*61046927SAndroid Build Coastguard Worker        radv_image_has_htile(image)) {
858*61046927SAndroid Build Coastguard Worker       image->clear_value_offset = image->size;
859*61046927SAndroid Build Coastguard Worker       image->size += 8 * image->vk.mip_levels;
860*61046927SAndroid Build Coastguard Worker    }
861*61046927SAndroid Build Coastguard Worker 
862*61046927SAndroid Build Coastguard Worker    if (radv_image_is_tc_compat_htile(image) && pdev->info.has_tc_compat_zrange_bug) {
863*61046927SAndroid Build Coastguard Worker       /* Metadata for the TC-compatible HTILE hardware bug which
864*61046927SAndroid Build Coastguard Worker        * have to be fixed by updating ZRANGE_PRECISION when doing
865*61046927SAndroid Build Coastguard Worker        * fast depth clears to 0.0f.
866*61046927SAndroid Build Coastguard Worker        */
867*61046927SAndroid Build Coastguard Worker       image->tc_compat_zrange_offset = image->size;
868*61046927SAndroid Build Coastguard Worker       image->size += image->vk.mip_levels * 4;
869*61046927SAndroid Build Coastguard Worker    }
870*61046927SAndroid Build Coastguard Worker }
871*61046927SAndroid Build Coastguard Worker 
872*61046927SAndroid Build Coastguard Worker /* Determine if the image is affected by the pipe misaligned metadata issue
873*61046927SAndroid Build Coastguard Worker  * which requires to invalidate L2.
874*61046927SAndroid Build Coastguard Worker  */
875*61046927SAndroid Build Coastguard Worker static bool
radv_image_is_pipe_misaligned(const struct radv_device * device,const struct radv_image * image)876*61046927SAndroid Build Coastguard Worker radv_image_is_pipe_misaligned(const struct radv_device *device, const struct radv_image *image)
877*61046927SAndroid Build Coastguard Worker {
878*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
879*61046927SAndroid Build Coastguard Worker    const struct radeon_info *gpu_info = &pdev->info;
880*61046927SAndroid Build Coastguard Worker    int log2_samples = util_logbase2(image->vk.samples);
881*61046927SAndroid Build Coastguard Worker 
882*61046927SAndroid Build Coastguard Worker    assert(gpu_info->gfx_level >= GFX10);
883*61046927SAndroid Build Coastguard Worker 
884*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < image->plane_count; ++i) {
885*61046927SAndroid Build Coastguard Worker       VkFormat fmt = radv_image_get_plane_format(pdev, image, i);
886*61046927SAndroid Build Coastguard Worker       int log2_bpp = util_logbase2(vk_format_get_blocksize(fmt));
887*61046927SAndroid Build Coastguard Worker       int log2_bpp_and_samples;
888*61046927SAndroid Build Coastguard Worker 
889*61046927SAndroid Build Coastguard Worker       if (gpu_info->gfx_level >= GFX10_3) {
890*61046927SAndroid Build Coastguard Worker          log2_bpp_and_samples = log2_bpp + log2_samples;
891*61046927SAndroid Build Coastguard Worker       } else {
892*61046927SAndroid Build Coastguard Worker          if (vk_format_has_depth(image->vk.format) && image->vk.array_layers >= 8) {
893*61046927SAndroid Build Coastguard Worker             log2_bpp = 2;
894*61046927SAndroid Build Coastguard Worker          }
895*61046927SAndroid Build Coastguard Worker 
896*61046927SAndroid Build Coastguard Worker          log2_bpp_and_samples = MIN2(6, log2_bpp + log2_samples);
897*61046927SAndroid Build Coastguard Worker       }
898*61046927SAndroid Build Coastguard Worker 
899*61046927SAndroid Build Coastguard Worker       int num_pipes = G_0098F8_NUM_PIPES(gpu_info->gb_addr_config);
900*61046927SAndroid Build Coastguard Worker       int overlap = MAX2(0, log2_bpp_and_samples + num_pipes - 8);
901*61046927SAndroid Build Coastguard Worker 
902*61046927SAndroid Build Coastguard Worker       if (vk_format_has_depth(image->vk.format)) {
903*61046927SAndroid Build Coastguard Worker          if (radv_image_is_tc_compat_htile(image) && overlap) {
904*61046927SAndroid Build Coastguard Worker             return true;
905*61046927SAndroid Build Coastguard Worker          }
906*61046927SAndroid Build Coastguard Worker       } else {
907*61046927SAndroid Build Coastguard Worker          int max_compressed_frags = G_0098F8_MAX_COMPRESSED_FRAGS(gpu_info->gb_addr_config);
908*61046927SAndroid Build Coastguard Worker          int log2_samples_frag_diff = MAX2(0, log2_samples - max_compressed_frags);
909*61046927SAndroid Build Coastguard Worker          int samples_overlap = MIN2(log2_samples, overlap);
910*61046927SAndroid Build Coastguard Worker 
911*61046927SAndroid Build Coastguard Worker          /* TODO: It shouldn't be necessary if the image has DCC but
912*61046927SAndroid Build Coastguard Worker           * not readable by shader.
913*61046927SAndroid Build Coastguard Worker           */
914*61046927SAndroid Build Coastguard Worker          if ((radv_image_has_dcc(image) || radv_image_is_tc_compat_cmask(image)) &&
915*61046927SAndroid Build Coastguard Worker              (samples_overlap > log2_samples_frag_diff)) {
916*61046927SAndroid Build Coastguard Worker             return true;
917*61046927SAndroid Build Coastguard Worker          }
918*61046927SAndroid Build Coastguard Worker       }
919*61046927SAndroid Build Coastguard Worker    }
920*61046927SAndroid Build Coastguard Worker 
921*61046927SAndroid Build Coastguard Worker    return false;
922*61046927SAndroid Build Coastguard Worker }
923*61046927SAndroid Build Coastguard Worker 
924*61046927SAndroid Build Coastguard Worker static bool
radv_image_is_l2_coherent(const struct radv_device * device,const struct radv_image * image)925*61046927SAndroid Build Coastguard Worker radv_image_is_l2_coherent(const struct radv_device *device, const struct radv_image *image)
926*61046927SAndroid Build Coastguard Worker {
927*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
928*61046927SAndroid Build Coastguard Worker 
929*61046927SAndroid Build Coastguard Worker    if (pdev->info.gfx_level >= GFX12) {
930*61046927SAndroid Build Coastguard Worker       return true; /* Everything is coherent with TC L2. */
931*61046927SAndroid Build Coastguard Worker    } else if (pdev->info.gfx_level >= GFX10) {
932*61046927SAndroid Build Coastguard Worker       return !pdev->info.tcc_rb_non_coherent && !radv_image_is_pipe_misaligned(device, image);
933*61046927SAndroid Build Coastguard Worker    } else if (pdev->info.gfx_level == GFX9) {
934*61046927SAndroid Build Coastguard Worker       if (image->vk.samples == 1 &&
935*61046927SAndroid Build Coastguard Worker           (image->vk.usage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) &&
936*61046927SAndroid Build Coastguard Worker           !vk_format_has_stencil(image->vk.format)) {
937*61046927SAndroid Build Coastguard Worker          /* Single-sample color and single-sample depth
938*61046927SAndroid Build Coastguard Worker           * (not stencil) are coherent with shaders on
939*61046927SAndroid Build Coastguard Worker           * GFX9.
940*61046927SAndroid Build Coastguard Worker           */
941*61046927SAndroid Build Coastguard Worker          return true;
942*61046927SAndroid Build Coastguard Worker       }
943*61046927SAndroid Build Coastguard Worker    }
944*61046927SAndroid Build Coastguard Worker 
945*61046927SAndroid Build Coastguard Worker    return false;
946*61046927SAndroid Build Coastguard Worker }
947*61046927SAndroid Build Coastguard Worker 
948*61046927SAndroid Build Coastguard Worker /**
949*61046927SAndroid Build Coastguard Worker  * Determine if the given image can be fast cleared.
950*61046927SAndroid Build Coastguard Worker  */
951*61046927SAndroid Build Coastguard Worker bool
radv_image_can_fast_clear(const struct radv_device * device,const struct radv_image * image)952*61046927SAndroid Build Coastguard Worker radv_image_can_fast_clear(const struct radv_device *device, const struct radv_image *image)
953*61046927SAndroid Build Coastguard Worker {
954*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
955*61046927SAndroid Build Coastguard Worker    const struct radv_instance *instance = radv_physical_device_instance(pdev);
956*61046927SAndroid Build Coastguard Worker 
957*61046927SAndroid Build Coastguard Worker    if (instance->debug_flags & RADV_DEBUG_NO_FAST_CLEARS)
958*61046927SAndroid Build Coastguard Worker       return false;
959*61046927SAndroid Build Coastguard Worker 
960*61046927SAndroid Build Coastguard Worker    if (vk_format_is_color(image->vk.format)) {
961*61046927SAndroid Build Coastguard Worker       if (!radv_image_has_cmask(image) && !radv_image_has_dcc(image))
962*61046927SAndroid Build Coastguard Worker          return false;
963*61046927SAndroid Build Coastguard Worker 
964*61046927SAndroid Build Coastguard Worker       /* RB+ doesn't work with CMASK fast clear on Stoney. */
965*61046927SAndroid Build Coastguard Worker       if (!radv_image_has_dcc(image) && pdev->info.family == CHIP_STONEY)
966*61046927SAndroid Build Coastguard Worker          return false;
967*61046927SAndroid Build Coastguard Worker 
968*61046927SAndroid Build Coastguard Worker       /* Fast-clears with CMASK aren't supported for 128-bit formats. */
969*61046927SAndroid Build Coastguard Worker       if (radv_image_has_cmask(image) && vk_format_get_blocksizebits(image->vk.format) > 64)
970*61046927SAndroid Build Coastguard Worker          return false;
971*61046927SAndroid Build Coastguard Worker    } else {
972*61046927SAndroid Build Coastguard Worker       if (!radv_image_has_htile(image))
973*61046927SAndroid Build Coastguard Worker          return false;
974*61046927SAndroid Build Coastguard Worker    }
975*61046927SAndroid Build Coastguard Worker 
976*61046927SAndroid Build Coastguard Worker    /* Do not fast clears 3D images. */
977*61046927SAndroid Build Coastguard Worker    if (image->vk.image_type == VK_IMAGE_TYPE_3D)
978*61046927SAndroid Build Coastguard Worker       return false;
979*61046927SAndroid Build Coastguard Worker 
980*61046927SAndroid Build Coastguard Worker    return true;
981*61046927SAndroid Build Coastguard Worker }
982*61046927SAndroid Build Coastguard Worker 
983*61046927SAndroid Build Coastguard Worker /**
984*61046927SAndroid Build Coastguard Worker  * Determine if the given image can be fast cleared using comp-to-single.
985*61046927SAndroid Build Coastguard Worker  */
986*61046927SAndroid Build Coastguard Worker static bool
radv_image_use_comp_to_single(const struct radv_device * device,const struct radv_image * image)987*61046927SAndroid Build Coastguard Worker radv_image_use_comp_to_single(const struct radv_device *device, const struct radv_image *image)
988*61046927SAndroid Build Coastguard Worker {
989*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
990*61046927SAndroid Build Coastguard Worker 
991*61046927SAndroid Build Coastguard Worker    /* comp-to-single is only available for GFX10+. */
992*61046927SAndroid Build Coastguard Worker    if (pdev->info.gfx_level < GFX10)
993*61046927SAndroid Build Coastguard Worker       return false;
994*61046927SAndroid Build Coastguard Worker 
995*61046927SAndroid Build Coastguard Worker    /* If the image can't be fast cleared, comp-to-single can't be used. */
996*61046927SAndroid Build Coastguard Worker    if (!radv_image_can_fast_clear(device, image))
997*61046927SAndroid Build Coastguard Worker       return false;
998*61046927SAndroid Build Coastguard Worker 
999*61046927SAndroid Build Coastguard Worker    /* If the image doesn't have DCC, it can't be fast cleared using comp-to-single */
1000*61046927SAndroid Build Coastguard Worker    if (!radv_image_has_dcc(image))
1001*61046927SAndroid Build Coastguard Worker       return false;
1002*61046927SAndroid Build Coastguard Worker 
1003*61046927SAndroid Build Coastguard Worker    /* It seems 8bpp and 16bpp require RB+ to work. */
1004*61046927SAndroid Build Coastguard Worker    unsigned bytes_per_pixel = vk_format_get_blocksize(image->vk.format);
1005*61046927SAndroid Build Coastguard Worker    if (bytes_per_pixel <= 2 && !pdev->info.rbplus_allowed)
1006*61046927SAndroid Build Coastguard Worker       return false;
1007*61046927SAndroid Build Coastguard Worker 
1008*61046927SAndroid Build Coastguard Worker    return true;
1009*61046927SAndroid Build Coastguard Worker }
1010*61046927SAndroid Build Coastguard Worker 
1011*61046927SAndroid Build Coastguard Worker static unsigned
radv_get_internal_plane_count(const struct radv_physical_device * pdev,VkFormat fmt)1012*61046927SAndroid Build Coastguard Worker radv_get_internal_plane_count(const struct radv_physical_device *pdev, VkFormat fmt)
1013*61046927SAndroid Build Coastguard Worker {
1014*61046927SAndroid Build Coastguard Worker    if (radv_is_format_emulated(pdev, fmt))
1015*61046927SAndroid Build Coastguard Worker       return 2;
1016*61046927SAndroid Build Coastguard Worker    return vk_format_get_plane_count(fmt);
1017*61046927SAndroid Build Coastguard Worker }
1018*61046927SAndroid Build Coastguard Worker 
1019*61046927SAndroid Build Coastguard Worker static void
radv_image_reset_layout(const struct radv_physical_device * pdev,struct radv_image * image)1020*61046927SAndroid Build Coastguard Worker radv_image_reset_layout(const struct radv_physical_device *pdev, struct radv_image *image)
1021*61046927SAndroid Build Coastguard Worker {
1022*61046927SAndroid Build Coastguard Worker    image->size = 0;
1023*61046927SAndroid Build Coastguard Worker    image->alignment = 1;
1024*61046927SAndroid Build Coastguard Worker 
1025*61046927SAndroid Build Coastguard Worker    image->tc_compatible_cmask = 0;
1026*61046927SAndroid Build Coastguard Worker    image->fce_pred_offset = image->dcc_pred_offset = 0;
1027*61046927SAndroid Build Coastguard Worker    image->clear_value_offset = image->tc_compat_zrange_offset = 0;
1028*61046927SAndroid Build Coastguard Worker 
1029*61046927SAndroid Build Coastguard Worker    unsigned plane_count = radv_get_internal_plane_count(pdev, image->vk.format);
1030*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < plane_count; ++i) {
1031*61046927SAndroid Build Coastguard Worker       VkFormat format = radv_image_get_plane_format(pdev, image, i);
1032*61046927SAndroid Build Coastguard Worker       if (vk_format_has_depth(format))
1033*61046927SAndroid Build Coastguard Worker          format = vk_format_depth_only(format);
1034*61046927SAndroid Build Coastguard Worker 
1035*61046927SAndroid Build Coastguard Worker       uint64_t flags = image->planes[i].surface.flags;
1036*61046927SAndroid Build Coastguard Worker       uint64_t modifier = image->planes[i].surface.modifier;
1037*61046927SAndroid Build Coastguard Worker       memset(image->planes + i, 0, sizeof(image->planes[i]));
1038*61046927SAndroid Build Coastguard Worker 
1039*61046927SAndroid Build Coastguard Worker       image->planes[i].surface.flags = flags;
1040*61046927SAndroid Build Coastguard Worker       image->planes[i].surface.modifier = modifier;
1041*61046927SAndroid Build Coastguard Worker       image->planes[i].surface.blk_w = vk_format_get_blockwidth(format);
1042*61046927SAndroid Build Coastguard Worker       image->planes[i].surface.blk_h = vk_format_get_blockheight(format);
1043*61046927SAndroid Build Coastguard Worker       image->planes[i].surface.bpe = vk_format_get_blocksize(format);
1044*61046927SAndroid Build Coastguard Worker 
1045*61046927SAndroid Build Coastguard Worker       /* align byte per element on dword */
1046*61046927SAndroid Build Coastguard Worker       if (image->planes[i].surface.bpe == 3) {
1047*61046927SAndroid Build Coastguard Worker          image->planes[i].surface.bpe = 4;
1048*61046927SAndroid Build Coastguard Worker       }
1049*61046927SAndroid Build Coastguard Worker    }
1050*61046927SAndroid Build Coastguard Worker }
1051*61046927SAndroid Build Coastguard Worker 
1052*61046927SAndroid Build Coastguard Worker struct ac_surf_info
radv_get_ac_surf_info(struct radv_device * device,const struct radv_image * image)1053*61046927SAndroid Build Coastguard Worker radv_get_ac_surf_info(struct radv_device *device, const struct radv_image *image)
1054*61046927SAndroid Build Coastguard Worker {
1055*61046927SAndroid Build Coastguard Worker    struct ac_surf_info info;
1056*61046927SAndroid Build Coastguard Worker 
1057*61046927SAndroid Build Coastguard Worker    memset(&info, 0, sizeof(info));
1058*61046927SAndroid Build Coastguard Worker 
1059*61046927SAndroid Build Coastguard Worker    info.width = image->vk.extent.width;
1060*61046927SAndroid Build Coastguard Worker    info.height = image->vk.extent.height;
1061*61046927SAndroid Build Coastguard Worker    info.depth = image->vk.extent.depth;
1062*61046927SAndroid Build Coastguard Worker    info.samples = image->vk.samples;
1063*61046927SAndroid Build Coastguard Worker    info.storage_samples = image->vk.samples;
1064*61046927SAndroid Build Coastguard Worker    info.array_size = image->vk.array_layers;
1065*61046927SAndroid Build Coastguard Worker    info.levels = image->vk.mip_levels;
1066*61046927SAndroid Build Coastguard Worker    info.num_channels = vk_format_get_nr_components(image->vk.format);
1067*61046927SAndroid Build Coastguard Worker 
1068*61046927SAndroid Build Coastguard Worker    if (!vk_format_is_depth_or_stencil(image->vk.format) && !image->shareable &&
1069*61046927SAndroid Build Coastguard Worker        !(image->vk.create_flags & (VK_IMAGE_CREATE_SPARSE_ALIASED_BIT | VK_IMAGE_CREATE_ALIAS_BIT)) &&
1070*61046927SAndroid Build Coastguard Worker        image->vk.tiling != VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) {
1071*61046927SAndroid Build Coastguard Worker       info.surf_index = &device->image_mrt_offset_counter;
1072*61046927SAndroid Build Coastguard Worker    }
1073*61046927SAndroid Build Coastguard Worker 
1074*61046927SAndroid Build Coastguard Worker    return info;
1075*61046927SAndroid Build Coastguard Worker }
1076*61046927SAndroid Build Coastguard Worker 
1077*61046927SAndroid Build Coastguard Worker VkResult
radv_image_create_layout(struct radv_device * device,struct radv_image_create_info create_info,const struct VkImageDrmFormatModifierExplicitCreateInfoEXT * mod_info,const struct VkVideoProfileListInfoKHR * profile_list,struct radv_image * image)1078*61046927SAndroid Build Coastguard Worker radv_image_create_layout(struct radv_device *device, struct radv_image_create_info create_info,
1079*61046927SAndroid Build Coastguard Worker                          const struct VkImageDrmFormatModifierExplicitCreateInfoEXT *mod_info,
1080*61046927SAndroid Build Coastguard Worker                          const struct VkVideoProfileListInfoKHR *profile_list, struct radv_image *image)
1081*61046927SAndroid Build Coastguard Worker {
1082*61046927SAndroid Build Coastguard Worker    struct radv_physical_device *pdev = radv_device_physical(device);
1083*61046927SAndroid Build Coastguard Worker 
1084*61046927SAndroid Build Coastguard Worker    /* Clear the pCreateInfo pointer so we catch issues in the delayed case when we test in the
1085*61046927SAndroid Build Coastguard Worker     * common internal case. */
1086*61046927SAndroid Build Coastguard Worker    create_info.vk_info = NULL;
1087*61046927SAndroid Build Coastguard Worker 
1088*61046927SAndroid Build Coastguard Worker    struct ac_surf_info image_info = radv_get_ac_surf_info(device, image);
1089*61046927SAndroid Build Coastguard Worker    VkResult result = radv_patch_image_from_extra_info(device, image, &create_info, &image_info);
1090*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
1091*61046927SAndroid Build Coastguard Worker       return result;
1092*61046927SAndroid Build Coastguard Worker 
1093*61046927SAndroid Build Coastguard Worker    assert(!mod_info || mod_info->drmFormatModifierPlaneCount >= image->plane_count);
1094*61046927SAndroid Build Coastguard Worker 
1095*61046927SAndroid Build Coastguard Worker    radv_image_reset_layout(pdev, image);
1096*61046927SAndroid Build Coastguard Worker 
1097*61046927SAndroid Build Coastguard Worker    /*
1098*61046927SAndroid Build Coastguard Worker     * Due to how the decoder works, the user can't supply an oversized image, because if it attempts
1099*61046927SAndroid Build Coastguard Worker     * to sample it later with a linear filter, it will get garbage after the height it wants,
1100*61046927SAndroid Build Coastguard Worker     * so we let the user specify the width/height unaligned, and align them preallocation.
1101*61046927SAndroid Build Coastguard Worker     */
1102*61046927SAndroid Build Coastguard Worker    if (image->vk.usage & (VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR |
1103*61046927SAndroid Build Coastguard Worker                           VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR |
1104*61046927SAndroid Build Coastguard Worker                           VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR)) {
1105*61046927SAndroid Build Coastguard Worker       if (!device->vk.enabled_features.videoMaintenance1)
1106*61046927SAndroid Build Coastguard Worker          assert(profile_list);
1107*61046927SAndroid Build Coastguard Worker       uint32_t width_align, height_align;
1108*61046927SAndroid Build Coastguard Worker       radv_video_get_profile_alignments(pdev, profile_list, &width_align, &height_align);
1109*61046927SAndroid Build Coastguard Worker       image_info.width = align(image_info.width, width_align);
1110*61046927SAndroid Build Coastguard Worker       image_info.height = align(image_info.height, height_align);
1111*61046927SAndroid Build Coastguard Worker 
1112*61046927SAndroid Build Coastguard Worker       if (radv_has_uvd(pdev) && image->vk.usage & VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR) {
1113*61046927SAndroid Build Coastguard Worker          /* UVD and kernel demand a full DPB allocation. */
1114*61046927SAndroid Build Coastguard Worker          image_info.array_size = MIN2(16, image_info.array_size);
1115*61046927SAndroid Build Coastguard Worker       }
1116*61046927SAndroid Build Coastguard Worker    }
1117*61046927SAndroid Build Coastguard Worker 
1118*61046927SAndroid Build Coastguard Worker    unsigned plane_count = radv_get_internal_plane_count(pdev, image->vk.format);
1119*61046927SAndroid Build Coastguard Worker    for (unsigned plane = 0; plane < plane_count; ++plane) {
1120*61046927SAndroid Build Coastguard Worker       struct ac_surf_info info = image_info;
1121*61046927SAndroid Build Coastguard Worker       uint64_t offset;
1122*61046927SAndroid Build Coastguard Worker       unsigned stride;
1123*61046927SAndroid Build Coastguard Worker 
1124*61046927SAndroid Build Coastguard Worker       info.width = vk_format_get_plane_width(image->vk.format, plane, info.width);
1125*61046927SAndroid Build Coastguard Worker       info.height = vk_format_get_plane_height(image->vk.format, plane, info.height);
1126*61046927SAndroid Build Coastguard Worker 
1127*61046927SAndroid Build Coastguard Worker       if (create_info.no_metadata_planes || plane_count > 1) {
1128*61046927SAndroid Build Coastguard Worker          image->planes[plane].surface.flags |= RADEON_SURF_DISABLE_DCC | RADEON_SURF_NO_FMASK | RADEON_SURF_NO_HTILE;
1129*61046927SAndroid Build Coastguard Worker       }
1130*61046927SAndroid Build Coastguard Worker 
1131*61046927SAndroid Build Coastguard Worker       device->ws->surface_init(device->ws, &info, &image->planes[plane].surface);
1132*61046927SAndroid Build Coastguard Worker 
1133*61046927SAndroid Build Coastguard Worker       if (plane == 0) {
1134*61046927SAndroid Build Coastguard Worker          if (!radv_use_dcc_for_image_late(device, image))
1135*61046927SAndroid Build Coastguard Worker             ac_surface_zero_dcc_fields(&image->planes[0].surface);
1136*61046927SAndroid Build Coastguard Worker       }
1137*61046927SAndroid Build Coastguard Worker 
1138*61046927SAndroid Build Coastguard Worker       if (create_info.bo_metadata && !mod_info &&
1139*61046927SAndroid Build Coastguard Worker           !ac_surface_apply_umd_metadata(&pdev->info, &image->planes[plane].surface, image->vk.samples,
1140*61046927SAndroid Build Coastguard Worker                                          image->vk.mip_levels, create_info.bo_metadata->size_metadata,
1141*61046927SAndroid Build Coastguard Worker                                          create_info.bo_metadata->metadata))
1142*61046927SAndroid Build Coastguard Worker          return VK_ERROR_INVALID_EXTERNAL_HANDLE;
1143*61046927SAndroid Build Coastguard Worker 
1144*61046927SAndroid Build Coastguard Worker       if (!create_info.no_metadata_planes && !create_info.bo_metadata && plane_count == 1 && !mod_info)
1145*61046927SAndroid Build Coastguard Worker          radv_image_alloc_single_sample_cmask(device, image, &image->planes[plane].surface);
1146*61046927SAndroid Build Coastguard Worker 
1147*61046927SAndroid Build Coastguard Worker       if (mod_info) {
1148*61046927SAndroid Build Coastguard Worker          if (mod_info->pPlaneLayouts[plane].rowPitch % image->planes[plane].surface.bpe ||
1149*61046927SAndroid Build Coastguard Worker              !mod_info->pPlaneLayouts[plane].rowPitch)
1150*61046927SAndroid Build Coastguard Worker             return VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT;
1151*61046927SAndroid Build Coastguard Worker 
1152*61046927SAndroid Build Coastguard Worker          offset = mod_info->pPlaneLayouts[plane].offset;
1153*61046927SAndroid Build Coastguard Worker          stride = mod_info->pPlaneLayouts[plane].rowPitch / image->planes[plane].surface.bpe;
1154*61046927SAndroid Build Coastguard Worker       } else {
1155*61046927SAndroid Build Coastguard Worker          offset = image->disjoint ? 0 : align64(image->size, 1ull << image->planes[plane].surface.alignment_log2);
1156*61046927SAndroid Build Coastguard Worker          stride = 0; /* 0 means no override */
1157*61046927SAndroid Build Coastguard Worker       }
1158*61046927SAndroid Build Coastguard Worker 
1159*61046927SAndroid Build Coastguard Worker       if (!ac_surface_override_offset_stride(&pdev->info, &image->planes[plane].surface, image->vk.array_layers,
1160*61046927SAndroid Build Coastguard Worker                                              image->vk.mip_levels, offset, stride))
1161*61046927SAndroid Build Coastguard Worker          return VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT;
1162*61046927SAndroid Build Coastguard Worker 
1163*61046927SAndroid Build Coastguard Worker       /* Validate DCC offsets in modifier layout. */
1164*61046927SAndroid Build Coastguard Worker       if (plane_count == 1 && mod_info) {
1165*61046927SAndroid Build Coastguard Worker          unsigned mem_planes = ac_surface_get_nplanes(&image->planes[plane].surface);
1166*61046927SAndroid Build Coastguard Worker          if (mod_info->drmFormatModifierPlaneCount != mem_planes)
1167*61046927SAndroid Build Coastguard Worker             return VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT;
1168*61046927SAndroid Build Coastguard Worker 
1169*61046927SAndroid Build Coastguard Worker          for (unsigned i = 1; i < mem_planes; ++i) {
1170*61046927SAndroid Build Coastguard Worker             if (ac_surface_get_plane_offset(pdev->info.gfx_level, &image->planes[plane].surface, i, 0) !=
1171*61046927SAndroid Build Coastguard Worker                 mod_info->pPlaneLayouts[i].offset)
1172*61046927SAndroid Build Coastguard Worker                return VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT;
1173*61046927SAndroid Build Coastguard Worker          }
1174*61046927SAndroid Build Coastguard Worker       }
1175*61046927SAndroid Build Coastguard Worker 
1176*61046927SAndroid Build Coastguard Worker       image->size = MAX2(image->size, offset + image->planes[plane].surface.total_size);
1177*61046927SAndroid Build Coastguard Worker       image->alignment = MAX2(image->alignment, 1 << image->planes[plane].surface.alignment_log2);
1178*61046927SAndroid Build Coastguard Worker 
1179*61046927SAndroid Build Coastguard Worker       image->planes[plane].format = radv_image_get_plane_format(pdev, image, plane);
1180*61046927SAndroid Build Coastguard Worker    }
1181*61046927SAndroid Build Coastguard Worker 
1182*61046927SAndroid Build Coastguard Worker    image->tc_compatible_cmask = radv_image_has_cmask(image) && radv_use_tc_compat_cmask_for_image(device, image);
1183*61046927SAndroid Build Coastguard Worker 
1184*61046927SAndroid Build Coastguard Worker    image->l2_coherent = radv_image_is_l2_coherent(device, image);
1185*61046927SAndroid Build Coastguard Worker 
1186*61046927SAndroid Build Coastguard Worker    image->support_comp_to_single = radv_image_use_comp_to_single(device, image);
1187*61046927SAndroid Build Coastguard Worker 
1188*61046927SAndroid Build Coastguard Worker    radv_image_alloc_values(device, image);
1189*61046927SAndroid Build Coastguard Worker 
1190*61046927SAndroid Build Coastguard Worker    assert(image->planes[0].surface.surf_size);
1191*61046927SAndroid Build Coastguard Worker    assert(image->planes[0].surface.modifier == DRM_FORMAT_MOD_INVALID ||
1192*61046927SAndroid Build Coastguard Worker           ac_modifier_has_dcc(image->planes[0].surface.modifier) == radv_image_has_dcc(image));
1193*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
1194*61046927SAndroid Build Coastguard Worker }
1195*61046927SAndroid Build Coastguard Worker 
1196*61046927SAndroid Build Coastguard Worker static void
radv_destroy_image(struct radv_device * device,const VkAllocationCallbacks * pAllocator,struct radv_image * image)1197*61046927SAndroid Build Coastguard Worker radv_destroy_image(struct radv_device *device, const VkAllocationCallbacks *pAllocator, struct radv_image *image)
1198*61046927SAndroid Build Coastguard Worker {
1199*61046927SAndroid Build Coastguard Worker    struct radv_physical_device *pdev = radv_device_physical(device);
1200*61046927SAndroid Build Coastguard Worker    struct radv_instance *instance = radv_physical_device_instance(pdev);
1201*61046927SAndroid Build Coastguard Worker 
1202*61046927SAndroid Build Coastguard Worker    if ((image->vk.create_flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT) && image->bindings[0].bo)
1203*61046927SAndroid Build Coastguard Worker       radv_bo_destroy(device, &image->vk.base, image->bindings[0].bo);
1204*61046927SAndroid Build Coastguard Worker 
1205*61046927SAndroid Build Coastguard Worker    if (image->owned_memory != VK_NULL_HANDLE) {
1206*61046927SAndroid Build Coastguard Worker       VK_FROM_HANDLE(radv_device_memory, mem, image->owned_memory);
1207*61046927SAndroid Build Coastguard Worker       radv_free_memory(device, pAllocator, mem);
1208*61046927SAndroid Build Coastguard Worker    }
1209*61046927SAndroid Build Coastguard Worker 
1210*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < ARRAY_SIZE(image->bindings); i++) {
1211*61046927SAndroid Build Coastguard Worker       if (!image->bindings[i].bo_va)
1212*61046927SAndroid Build Coastguard Worker          continue;
1213*61046927SAndroid Build Coastguard Worker 
1214*61046927SAndroid Build Coastguard Worker       vk_address_binding_report(&instance->vk, &image->vk.base, image->bindings[i].bo_va + image->bindings[i].offset,
1215*61046927SAndroid Build Coastguard Worker                                 image->bindings[i].range, VK_DEVICE_ADDRESS_BINDING_TYPE_UNBIND_EXT);
1216*61046927SAndroid Build Coastguard Worker    }
1217*61046927SAndroid Build Coastguard Worker 
1218*61046927SAndroid Build Coastguard Worker    radv_rmv_log_resource_destroy(device, (uint64_t)radv_image_to_handle(image));
1219*61046927SAndroid Build Coastguard Worker    vk_image_finish(&image->vk);
1220*61046927SAndroid Build Coastguard Worker    vk_free2(&device->vk.alloc, pAllocator, image);
1221*61046927SAndroid Build Coastguard Worker }
1222*61046927SAndroid Build Coastguard Worker 
1223*61046927SAndroid Build Coastguard Worker static void
radv_image_print_info(struct radv_device * device,struct radv_image * image)1224*61046927SAndroid Build Coastguard Worker radv_image_print_info(struct radv_device *device, struct radv_image *image)
1225*61046927SAndroid Build Coastguard Worker {
1226*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
1227*61046927SAndroid Build Coastguard Worker 
1228*61046927SAndroid Build Coastguard Worker    fprintf(stderr, "Image:\n");
1229*61046927SAndroid Build Coastguard Worker    fprintf(stderr,
1230*61046927SAndroid Build Coastguard Worker            "  Info: size=%" PRIu64 ", alignment=%" PRIu32 ", "
1231*61046927SAndroid Build Coastguard Worker            "width=%" PRIu32 ", height=%" PRIu32 ", depth=%" PRIu32 ", "
1232*61046927SAndroid Build Coastguard Worker            "array_size=%" PRIu32 ", levels=%" PRIu32 "\n",
1233*61046927SAndroid Build Coastguard Worker            image->size, image->alignment, image->vk.extent.width, image->vk.extent.height, image->vk.extent.depth,
1234*61046927SAndroid Build Coastguard Worker            image->vk.array_layers, image->vk.mip_levels);
1235*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < image->plane_count; ++i) {
1236*61046927SAndroid Build Coastguard Worker       const struct radv_image_plane *plane = &image->planes[i];
1237*61046927SAndroid Build Coastguard Worker       const struct radeon_surf *surf = &plane->surface;
1238*61046927SAndroid Build Coastguard Worker       const struct util_format_description *desc = vk_format_description(plane->format);
1239*61046927SAndroid Build Coastguard Worker       uint64_t offset = ac_surface_get_plane_offset(pdev->info.gfx_level, &plane->surface, 0, 0);
1240*61046927SAndroid Build Coastguard Worker 
1241*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "  Plane[%u]: vkformat=%s, offset=%" PRIu64 "\n", i, desc->name, offset);
1242*61046927SAndroid Build Coastguard Worker 
1243*61046927SAndroid Build Coastguard Worker       ac_surface_print_info(stderr, &pdev->info, surf);
1244*61046927SAndroid Build Coastguard Worker    }
1245*61046927SAndroid Build Coastguard Worker }
1246*61046927SAndroid Build Coastguard Worker 
1247*61046927SAndroid Build Coastguard Worker static uint64_t
radv_select_modifier(const struct radv_device * dev,VkFormat format,const struct VkImageDrmFormatModifierListCreateInfoEXT * mod_list)1248*61046927SAndroid Build Coastguard Worker radv_select_modifier(const struct radv_device *dev, VkFormat format,
1249*61046927SAndroid Build Coastguard Worker                      const struct VkImageDrmFormatModifierListCreateInfoEXT *mod_list)
1250*61046927SAndroid Build Coastguard Worker {
1251*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(dev);
1252*61046927SAndroid Build Coastguard Worker    unsigned mod_count;
1253*61046927SAndroid Build Coastguard Worker 
1254*61046927SAndroid Build Coastguard Worker    assert(mod_list->drmFormatModifierCount);
1255*61046927SAndroid Build Coastguard Worker 
1256*61046927SAndroid Build Coastguard Worker    /* We can allow everything here as it does not affect order and the application
1257*61046927SAndroid Build Coastguard Worker     * is only allowed to specify modifiers that we support. */
1258*61046927SAndroid Build Coastguard Worker    const struct ac_modifier_options modifier_options = {
1259*61046927SAndroid Build Coastguard Worker       .dcc = true,
1260*61046927SAndroid Build Coastguard Worker       .dcc_retile = true,
1261*61046927SAndroid Build Coastguard Worker    };
1262*61046927SAndroid Build Coastguard Worker 
1263*61046927SAndroid Build Coastguard Worker    ac_get_supported_modifiers(&pdev->info, &modifier_options, vk_format_to_pipe_format(format), &mod_count, NULL);
1264*61046927SAndroid Build Coastguard Worker 
1265*61046927SAndroid Build Coastguard Worker    uint64_t *mods = calloc(mod_count, sizeof(*mods));
1266*61046927SAndroid Build Coastguard Worker 
1267*61046927SAndroid Build Coastguard Worker    /* If allocations fail, fall back to a dumber solution. */
1268*61046927SAndroid Build Coastguard Worker    if (!mods)
1269*61046927SAndroid Build Coastguard Worker       return mod_list->pDrmFormatModifiers[0];
1270*61046927SAndroid Build Coastguard Worker 
1271*61046927SAndroid Build Coastguard Worker    ac_get_supported_modifiers(&pdev->info, &modifier_options, vk_format_to_pipe_format(format), &mod_count, mods);
1272*61046927SAndroid Build Coastguard Worker 
1273*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < mod_count; ++i) {
1274*61046927SAndroid Build Coastguard Worker       for (uint32_t j = 0; j < mod_list->drmFormatModifierCount; ++j) {
1275*61046927SAndroid Build Coastguard Worker          if (mods[i] == mod_list->pDrmFormatModifiers[j]) {
1276*61046927SAndroid Build Coastguard Worker             free(mods);
1277*61046927SAndroid Build Coastguard Worker             return mod_list->pDrmFormatModifiers[j];
1278*61046927SAndroid Build Coastguard Worker          }
1279*61046927SAndroid Build Coastguard Worker       }
1280*61046927SAndroid Build Coastguard Worker    }
1281*61046927SAndroid Build Coastguard Worker    unreachable("App specified an invalid modifier");
1282*61046927SAndroid Build Coastguard Worker }
1283*61046927SAndroid Build Coastguard Worker 
1284*61046927SAndroid Build Coastguard Worker VkResult
radv_image_create(VkDevice _device,const struct radv_image_create_info * create_info,const VkAllocationCallbacks * alloc,VkImage * pImage,bool is_internal)1285*61046927SAndroid Build Coastguard Worker radv_image_create(VkDevice _device, const struct radv_image_create_info *create_info,
1286*61046927SAndroid Build Coastguard Worker                   const VkAllocationCallbacks *alloc, VkImage *pImage, bool is_internal)
1287*61046927SAndroid Build Coastguard Worker {
1288*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(radv_device, device, _device);
1289*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
1290*61046927SAndroid Build Coastguard Worker    const struct radv_instance *instance = radv_physical_device_instance(pdev);
1291*61046927SAndroid Build Coastguard Worker    const VkImageCreateInfo *pCreateInfo = create_info->vk_info;
1292*61046927SAndroid Build Coastguard Worker    uint64_t modifier = DRM_FORMAT_MOD_INVALID;
1293*61046927SAndroid Build Coastguard Worker    struct radv_image *image = NULL;
1294*61046927SAndroid Build Coastguard Worker    VkFormat format = radv_select_android_external_format(pCreateInfo->pNext, pCreateInfo->format);
1295*61046927SAndroid Build Coastguard Worker    const struct VkImageDrmFormatModifierListCreateInfoEXT *mod_list =
1296*61046927SAndroid Build Coastguard Worker       vk_find_struct_const(pCreateInfo->pNext, IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT);
1297*61046927SAndroid Build Coastguard Worker    const struct VkImageDrmFormatModifierExplicitCreateInfoEXT *explicit_mod =
1298*61046927SAndroid Build Coastguard Worker       vk_find_struct_const(pCreateInfo->pNext, IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT);
1299*61046927SAndroid Build Coastguard Worker    assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO);
1300*61046927SAndroid Build Coastguard Worker    const struct VkVideoProfileListInfoKHR *profile_list =
1301*61046927SAndroid Build Coastguard Worker       vk_find_struct_const(pCreateInfo->pNext, VIDEO_PROFILE_LIST_INFO_KHR);
1302*61046927SAndroid Build Coastguard Worker 
1303*61046927SAndroid Build Coastguard Worker    unsigned plane_count = radv_get_internal_plane_count(pdev, format);
1304*61046927SAndroid Build Coastguard Worker 
1305*61046927SAndroid Build Coastguard Worker    const size_t image_struct_size = sizeof(*image) + sizeof(struct radv_image_plane) * plane_count;
1306*61046927SAndroid Build Coastguard Worker 
1307*61046927SAndroid Build Coastguard Worker    image = vk_zalloc2(&device->vk.alloc, alloc, image_struct_size, 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
1308*61046927SAndroid Build Coastguard Worker    if (!image)
1309*61046927SAndroid Build Coastguard Worker       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
1310*61046927SAndroid Build Coastguard Worker 
1311*61046927SAndroid Build Coastguard Worker    vk_image_init(&device->vk, &image->vk, pCreateInfo);
1312*61046927SAndroid Build Coastguard Worker 
1313*61046927SAndroid Build Coastguard Worker    image->plane_count = vk_format_get_plane_count(format);
1314*61046927SAndroid Build Coastguard Worker    image->disjoint = image->plane_count > 1 && pCreateInfo->flags & VK_IMAGE_CREATE_DISJOINT_BIT;
1315*61046927SAndroid Build Coastguard Worker 
1316*61046927SAndroid Build Coastguard Worker    image->exclusive = pCreateInfo->sharingMode == VK_SHARING_MODE_EXCLUSIVE;
1317*61046927SAndroid Build Coastguard Worker    if (pCreateInfo->sharingMode == VK_SHARING_MODE_CONCURRENT) {
1318*61046927SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < pCreateInfo->queueFamilyIndexCount; ++i)
1319*61046927SAndroid Build Coastguard Worker          if (pCreateInfo->pQueueFamilyIndices[i] == VK_QUEUE_FAMILY_EXTERNAL ||
1320*61046927SAndroid Build Coastguard Worker              pCreateInfo->pQueueFamilyIndices[i] == VK_QUEUE_FAMILY_FOREIGN_EXT)
1321*61046927SAndroid Build Coastguard Worker             image->queue_family_mask |= (1u << RADV_MAX_QUEUE_FAMILIES) - 1u;
1322*61046927SAndroid Build Coastguard Worker          else
1323*61046927SAndroid Build Coastguard Worker             image->queue_family_mask |= 1u << vk_queue_to_radv(pdev, pCreateInfo->pQueueFamilyIndices[i]);
1324*61046927SAndroid Build Coastguard Worker 
1325*61046927SAndroid Build Coastguard Worker       /* This queue never really accesses the image. */
1326*61046927SAndroid Build Coastguard Worker       image->queue_family_mask &= ~(1u << RADV_QUEUE_SPARSE);
1327*61046927SAndroid Build Coastguard Worker    }
1328*61046927SAndroid Build Coastguard Worker 
1329*61046927SAndroid Build Coastguard Worker    const VkExternalMemoryImageCreateInfo *external_info =
1330*61046927SAndroid Build Coastguard Worker       vk_find_struct_const(pCreateInfo->pNext, EXTERNAL_MEMORY_IMAGE_CREATE_INFO);
1331*61046927SAndroid Build Coastguard Worker 
1332*61046927SAndroid Build Coastguard Worker    image->shareable = external_info;
1333*61046927SAndroid Build Coastguard Worker 
1334*61046927SAndroid Build Coastguard Worker    if (mod_list)
1335*61046927SAndroid Build Coastguard Worker       modifier = radv_select_modifier(device, format, mod_list);
1336*61046927SAndroid Build Coastguard Worker    else if (explicit_mod)
1337*61046927SAndroid Build Coastguard Worker       modifier = explicit_mod->drmFormatModifier;
1338*61046927SAndroid Build Coastguard Worker 
1339*61046927SAndroid Build Coastguard Worker    for (unsigned plane = 0; plane < plane_count; ++plane) {
1340*61046927SAndroid Build Coastguard Worker       image->planes[plane].surface.flags = radv_get_surface_flags(device, image, plane, pCreateInfo, format);
1341*61046927SAndroid Build Coastguard Worker       image->planes[plane].surface.modifier = modifier;
1342*61046927SAndroid Build Coastguard Worker    }
1343*61046927SAndroid Build Coastguard Worker 
1344*61046927SAndroid Build Coastguard Worker    if (image->vk.external_handle_types & VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID) {
1345*61046927SAndroid Build Coastguard Worker #if DETECT_OS_ANDROID
1346*61046927SAndroid Build Coastguard Worker       image->vk.ahb_format = radv_ahb_format_for_vk_format(image->vk.format);
1347*61046927SAndroid Build Coastguard Worker #endif
1348*61046927SAndroid Build Coastguard Worker 
1349*61046927SAndroid Build Coastguard Worker       *pImage = radv_image_to_handle(image);
1350*61046927SAndroid Build Coastguard Worker       assert(!(image->vk.create_flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT));
1351*61046927SAndroid Build Coastguard Worker       return VK_SUCCESS;
1352*61046927SAndroid Build Coastguard Worker    }
1353*61046927SAndroid Build Coastguard Worker 
1354*61046927SAndroid Build Coastguard Worker    VkResult result = radv_image_create_layout(device, *create_info, explicit_mod, profile_list, image);
1355*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS) {
1356*61046927SAndroid Build Coastguard Worker       radv_destroy_image(device, alloc, image);
1357*61046927SAndroid Build Coastguard Worker       return result;
1358*61046927SAndroid Build Coastguard Worker    }
1359*61046927SAndroid Build Coastguard Worker 
1360*61046927SAndroid Build Coastguard Worker    if (image->vk.create_flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT) {
1361*61046927SAndroid Build Coastguard Worker       image->alignment = MAX2(image->alignment, 4096);
1362*61046927SAndroid Build Coastguard Worker       image->size = align64(image->size, image->alignment);
1363*61046927SAndroid Build Coastguard Worker       image->bindings[0].offset = 0;
1364*61046927SAndroid Build Coastguard Worker 
1365*61046927SAndroid Build Coastguard Worker       result = radv_bo_create(device, &image->vk.base, image->size, image->alignment, 0, RADEON_FLAG_VIRTUAL,
1366*61046927SAndroid Build Coastguard Worker                               RADV_BO_PRIORITY_VIRTUAL, 0, true, &image->bindings[0].bo);
1367*61046927SAndroid Build Coastguard Worker       if (result != VK_SUCCESS) {
1368*61046927SAndroid Build Coastguard Worker          radv_destroy_image(device, alloc, image);
1369*61046927SAndroid Build Coastguard Worker          return vk_error(device, result);
1370*61046927SAndroid Build Coastguard Worker       }
1371*61046927SAndroid Build Coastguard Worker    }
1372*61046927SAndroid Build Coastguard Worker 
1373*61046927SAndroid Build Coastguard Worker    if (instance->debug_flags & RADV_DEBUG_IMG) {
1374*61046927SAndroid Build Coastguard Worker       radv_image_print_info(device, image);
1375*61046927SAndroid Build Coastguard Worker    }
1376*61046927SAndroid Build Coastguard Worker 
1377*61046927SAndroid Build Coastguard Worker    *pImage = radv_image_to_handle(image);
1378*61046927SAndroid Build Coastguard Worker 
1379*61046927SAndroid Build Coastguard Worker    radv_rmv_log_image_create(device, pCreateInfo, is_internal, *pImage);
1380*61046927SAndroid Build Coastguard Worker    if (image->bindings[0].bo)
1381*61046927SAndroid Build Coastguard Worker       radv_rmv_log_image_bind(device, 0, *pImage);
1382*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
1383*61046927SAndroid Build Coastguard Worker }
1384*61046927SAndroid Build Coastguard Worker 
1385*61046927SAndroid Build Coastguard Worker unsigned
radv_plane_from_aspect(VkImageAspectFlags mask)1386*61046927SAndroid Build Coastguard Worker radv_plane_from_aspect(VkImageAspectFlags mask)
1387*61046927SAndroid Build Coastguard Worker {
1388*61046927SAndroid Build Coastguard Worker    switch (mask) {
1389*61046927SAndroid Build Coastguard Worker    case VK_IMAGE_ASPECT_PLANE_1_BIT:
1390*61046927SAndroid Build Coastguard Worker    case VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT:
1391*61046927SAndroid Build Coastguard Worker       return 1;
1392*61046927SAndroid Build Coastguard Worker    case VK_IMAGE_ASPECT_PLANE_2_BIT:
1393*61046927SAndroid Build Coastguard Worker    case VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT:
1394*61046927SAndroid Build Coastguard Worker       return 2;
1395*61046927SAndroid Build Coastguard Worker    case VK_IMAGE_ASPECT_MEMORY_PLANE_3_BIT_EXT:
1396*61046927SAndroid Build Coastguard Worker       return 3;
1397*61046927SAndroid Build Coastguard Worker    default:
1398*61046927SAndroid Build Coastguard Worker       return 0;
1399*61046927SAndroid Build Coastguard Worker    }
1400*61046927SAndroid Build Coastguard Worker }
1401*61046927SAndroid Build Coastguard Worker 
1402*61046927SAndroid Build Coastguard Worker VkFormat
radv_get_aspect_format(struct radv_image * image,VkImageAspectFlags mask)1403*61046927SAndroid Build Coastguard Worker radv_get_aspect_format(struct radv_image *image, VkImageAspectFlags mask)
1404*61046927SAndroid Build Coastguard Worker {
1405*61046927SAndroid Build Coastguard Worker    switch (mask) {
1406*61046927SAndroid Build Coastguard Worker    case VK_IMAGE_ASPECT_PLANE_0_BIT:
1407*61046927SAndroid Build Coastguard Worker       return image->planes[0].format;
1408*61046927SAndroid Build Coastguard Worker    case VK_IMAGE_ASPECT_PLANE_1_BIT:
1409*61046927SAndroid Build Coastguard Worker       return image->planes[1].format;
1410*61046927SAndroid Build Coastguard Worker    case VK_IMAGE_ASPECT_PLANE_2_BIT:
1411*61046927SAndroid Build Coastguard Worker       return image->planes[2].format;
1412*61046927SAndroid Build Coastguard Worker    case VK_IMAGE_ASPECT_STENCIL_BIT:
1413*61046927SAndroid Build Coastguard Worker       return vk_format_stencil_only(image->vk.format);
1414*61046927SAndroid Build Coastguard Worker    case VK_IMAGE_ASPECT_DEPTH_BIT:
1415*61046927SAndroid Build Coastguard Worker       return vk_format_depth_only(image->vk.format);
1416*61046927SAndroid Build Coastguard Worker    case VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT:
1417*61046927SAndroid Build Coastguard Worker       return vk_format_depth_only(image->vk.format);
1418*61046927SAndroid Build Coastguard Worker    default:
1419*61046927SAndroid Build Coastguard Worker       return image->vk.format;
1420*61046927SAndroid Build Coastguard Worker    }
1421*61046927SAndroid Build Coastguard Worker }
1422*61046927SAndroid Build Coastguard Worker 
1423*61046927SAndroid Build Coastguard Worker bool
radv_layout_is_htile_compressed(const struct radv_device * device,const struct radv_image * image,VkImageLayout layout,unsigned queue_mask)1424*61046927SAndroid Build Coastguard Worker radv_layout_is_htile_compressed(const struct radv_device *device, const struct radv_image *image, VkImageLayout layout,
1425*61046927SAndroid Build Coastguard Worker                                 unsigned queue_mask)
1426*61046927SAndroid Build Coastguard Worker {
1427*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
1428*61046927SAndroid Build Coastguard Worker    const struct radv_instance *instance = radv_physical_device_instance(pdev);
1429*61046927SAndroid Build Coastguard Worker 
1430*61046927SAndroid Build Coastguard Worker    /* Don't compress exclusive images used on transfer queues when SDMA doesn't support HTILE.
1431*61046927SAndroid Build Coastguard Worker     * Note that HTILE is already disabled on concurrent images when not supported.
1432*61046927SAndroid Build Coastguard Worker     */
1433*61046927SAndroid Build Coastguard Worker    if (queue_mask == BITFIELD_BIT(RADV_QUEUE_TRANSFER) && !pdev->info.sdma_supports_compression)
1434*61046927SAndroid Build Coastguard Worker       return false;
1435*61046927SAndroid Build Coastguard Worker 
1436*61046927SAndroid Build Coastguard Worker    switch (layout) {
1437*61046927SAndroid Build Coastguard Worker    case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
1438*61046927SAndroid Build Coastguard Worker    case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL:
1439*61046927SAndroid Build Coastguard Worker    case VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL:
1440*61046927SAndroid Build Coastguard Worker    case VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL:
1441*61046927SAndroid Build Coastguard Worker       return radv_image_has_htile(image);
1442*61046927SAndroid Build Coastguard Worker    case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
1443*61046927SAndroid Build Coastguard Worker       return radv_image_is_tc_compat_htile(image) ||
1444*61046927SAndroid Build Coastguard Worker              (radv_image_has_htile(image) && queue_mask == (1u << RADV_QUEUE_GENERAL));
1445*61046927SAndroid Build Coastguard Worker    case VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR:
1446*61046927SAndroid Build Coastguard Worker    case VK_IMAGE_LAYOUT_GENERAL:
1447*61046927SAndroid Build Coastguard Worker       /* It should be safe to enable TC-compat HTILE with
1448*61046927SAndroid Build Coastguard Worker        * VK_IMAGE_LAYOUT_GENERAL if we are not in a render loop and
1449*61046927SAndroid Build Coastguard Worker        * if the image doesn't have the storage bit set. This
1450*61046927SAndroid Build Coastguard Worker        * improves performance for apps that use GENERAL for the main
1451*61046927SAndroid Build Coastguard Worker        * depth pass because this allows compression and this reduces
1452*61046927SAndroid Build Coastguard Worker        * the number of decompressions from/to GENERAL.
1453*61046927SAndroid Build Coastguard Worker        */
1454*61046927SAndroid Build Coastguard Worker       if (radv_image_is_tc_compat_htile(image) && queue_mask & (1u << RADV_QUEUE_GENERAL) &&
1455*61046927SAndroid Build Coastguard Worker           !instance->drirc.disable_tc_compat_htile_in_general) {
1456*61046927SAndroid Build Coastguard Worker          return true;
1457*61046927SAndroid Build Coastguard Worker       } else {
1458*61046927SAndroid Build Coastguard Worker          return false;
1459*61046927SAndroid Build Coastguard Worker       }
1460*61046927SAndroid Build Coastguard Worker    case VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT:
1461*61046927SAndroid Build Coastguard Worker       /* Do not compress HTILE with feedback loops because we can't read&write it without
1462*61046927SAndroid Build Coastguard Worker        * introducing corruption.
1463*61046927SAndroid Build Coastguard Worker        */
1464*61046927SAndroid Build Coastguard Worker       return false;
1465*61046927SAndroid Build Coastguard Worker    case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
1466*61046927SAndroid Build Coastguard Worker    case VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL:
1467*61046927SAndroid Build Coastguard Worker       if (radv_image_is_tc_compat_htile(image) ||
1468*61046927SAndroid Build Coastguard Worker           (radv_image_has_htile(image) &&
1469*61046927SAndroid Build Coastguard Worker            !(image->vk.usage & (VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)))) {
1470*61046927SAndroid Build Coastguard Worker          /* Keep HTILE compressed if the image is only going to
1471*61046927SAndroid Build Coastguard Worker           * be used as a depth/stencil read-only attachment.
1472*61046927SAndroid Build Coastguard Worker           */
1473*61046927SAndroid Build Coastguard Worker          return true;
1474*61046927SAndroid Build Coastguard Worker       } else {
1475*61046927SAndroid Build Coastguard Worker          return false;
1476*61046927SAndroid Build Coastguard Worker       }
1477*61046927SAndroid Build Coastguard Worker       break;
1478*61046927SAndroid Build Coastguard Worker    default:
1479*61046927SAndroid Build Coastguard Worker       return radv_image_is_tc_compat_htile(image);
1480*61046927SAndroid Build Coastguard Worker    }
1481*61046927SAndroid Build Coastguard Worker }
1482*61046927SAndroid Build Coastguard Worker 
1483*61046927SAndroid Build Coastguard Worker bool
radv_layout_can_fast_clear(const struct radv_device * device,const struct radv_image * image,unsigned level,VkImageLayout layout,unsigned queue_mask)1484*61046927SAndroid Build Coastguard Worker radv_layout_can_fast_clear(const struct radv_device *device, const struct radv_image *image, unsigned level,
1485*61046927SAndroid Build Coastguard Worker                            VkImageLayout layout, unsigned queue_mask)
1486*61046927SAndroid Build Coastguard Worker {
1487*61046927SAndroid Build Coastguard Worker    if (radv_dcc_enabled(image, level) && !radv_layout_dcc_compressed(device, image, level, layout, queue_mask))
1488*61046927SAndroid Build Coastguard Worker       return false;
1489*61046927SAndroid Build Coastguard Worker 
1490*61046927SAndroid Build Coastguard Worker    if (!(image->vk.usage & RADV_IMAGE_USAGE_WRITE_BITS))
1491*61046927SAndroid Build Coastguard Worker       return false;
1492*61046927SAndroid Build Coastguard Worker 
1493*61046927SAndroid Build Coastguard Worker    if (layout != VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL && layout != VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL)
1494*61046927SAndroid Build Coastguard Worker       return false;
1495*61046927SAndroid Build Coastguard Worker 
1496*61046927SAndroid Build Coastguard Worker    /* Exclusive images with CMASK or DCC can always be fast-cleared on the gfx queue. Concurrent
1497*61046927SAndroid Build Coastguard Worker     * images can only be fast-cleared if comp-to-single is supported because we don't yet support
1498*61046927SAndroid Build Coastguard Worker     * FCE on the compute queue.
1499*61046927SAndroid Build Coastguard Worker     */
1500*61046927SAndroid Build Coastguard Worker    return queue_mask == (1u << RADV_QUEUE_GENERAL) || radv_image_use_comp_to_single(device, image);
1501*61046927SAndroid Build Coastguard Worker }
1502*61046927SAndroid Build Coastguard Worker 
1503*61046927SAndroid Build Coastguard Worker bool
radv_layout_dcc_compressed(const struct radv_device * device,const struct radv_image * image,unsigned level,VkImageLayout layout,unsigned queue_mask)1504*61046927SAndroid Build Coastguard Worker radv_layout_dcc_compressed(const struct radv_device *device, const struct radv_image *image, unsigned level,
1505*61046927SAndroid Build Coastguard Worker                            VkImageLayout layout, unsigned queue_mask)
1506*61046927SAndroid Build Coastguard Worker {
1507*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
1508*61046927SAndroid Build Coastguard Worker 
1509*61046927SAndroid Build Coastguard Worker    if (!radv_dcc_enabled(image, level))
1510*61046927SAndroid Build Coastguard Worker       return false;
1511*61046927SAndroid Build Coastguard Worker 
1512*61046927SAndroid Build Coastguard Worker    if (image->vk.tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT && queue_mask & (1u << RADV_QUEUE_FOREIGN))
1513*61046927SAndroid Build Coastguard Worker       return true;
1514*61046927SAndroid Build Coastguard Worker 
1515*61046927SAndroid Build Coastguard Worker    /* If the image is read-only, we can always just keep it compressed */
1516*61046927SAndroid Build Coastguard Worker    if (!(image->vk.usage & RADV_IMAGE_USAGE_WRITE_BITS))
1517*61046927SAndroid Build Coastguard Worker       return true;
1518*61046927SAndroid Build Coastguard Worker 
1519*61046927SAndroid Build Coastguard Worker    /* Don't compress compute transfer dst when image stores are not supported. */
1520*61046927SAndroid Build Coastguard Worker    if ((layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL || layout == VK_IMAGE_LAYOUT_GENERAL) &&
1521*61046927SAndroid Build Coastguard Worker        (queue_mask & (1u << RADV_QUEUE_COMPUTE)) && !radv_image_use_dcc_image_stores(device, image))
1522*61046927SAndroid Build Coastguard Worker       return false;
1523*61046927SAndroid Build Coastguard Worker 
1524*61046927SAndroid Build Coastguard Worker    /* Don't compress exclusive images used on transfer queues when SDMA doesn't support DCC.
1525*61046927SAndroid Build Coastguard Worker     * Note that DCC is already disabled on concurrent images when not supported.
1526*61046927SAndroid Build Coastguard Worker     */
1527*61046927SAndroid Build Coastguard Worker    if (queue_mask == BITFIELD_BIT(RADV_QUEUE_TRANSFER) && !pdev->info.sdma_supports_compression)
1528*61046927SAndroid Build Coastguard Worker       return false;
1529*61046927SAndroid Build Coastguard Worker 
1530*61046927SAndroid Build Coastguard Worker    if (layout == VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT) {
1531*61046927SAndroid Build Coastguard Worker       /* Do not compress DCC with feedback loops because we can't read&write it without introducing
1532*61046927SAndroid Build Coastguard Worker        * corruption.
1533*61046927SAndroid Build Coastguard Worker        */
1534*61046927SAndroid Build Coastguard Worker       return false;
1535*61046927SAndroid Build Coastguard Worker    }
1536*61046927SAndroid Build Coastguard Worker 
1537*61046927SAndroid Build Coastguard Worker    return pdev->info.gfx_level >= GFX10 || layout != VK_IMAGE_LAYOUT_GENERAL;
1538*61046927SAndroid Build Coastguard Worker }
1539*61046927SAndroid Build Coastguard Worker 
1540*61046927SAndroid Build Coastguard Worker enum radv_fmask_compression
radv_layout_fmask_compression(const struct radv_device * device,const struct radv_image * image,VkImageLayout layout,unsigned queue_mask)1541*61046927SAndroid Build Coastguard Worker radv_layout_fmask_compression(const struct radv_device *device, const struct radv_image *image, VkImageLayout layout,
1542*61046927SAndroid Build Coastguard Worker                               unsigned queue_mask)
1543*61046927SAndroid Build Coastguard Worker {
1544*61046927SAndroid Build Coastguard Worker    if (!radv_image_has_fmask(image))
1545*61046927SAndroid Build Coastguard Worker       return RADV_FMASK_COMPRESSION_NONE;
1546*61046927SAndroid Build Coastguard Worker 
1547*61046927SAndroid Build Coastguard Worker    if (layout == VK_IMAGE_LAYOUT_GENERAL)
1548*61046927SAndroid Build Coastguard Worker       return RADV_FMASK_COMPRESSION_NONE;
1549*61046927SAndroid Build Coastguard Worker 
1550*61046927SAndroid Build Coastguard Worker    /* Don't compress compute transfer dst because image stores ignore FMASK and it needs to be
1551*61046927SAndroid Build Coastguard Worker     * expanded before.
1552*61046927SAndroid Build Coastguard Worker     */
1553*61046927SAndroid Build Coastguard Worker    if (layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && (queue_mask & (1u << RADV_QUEUE_COMPUTE)))
1554*61046927SAndroid Build Coastguard Worker       return RADV_FMASK_COMPRESSION_NONE;
1555*61046927SAndroid Build Coastguard Worker 
1556*61046927SAndroid Build Coastguard Worker    /* Compress images if TC-compat CMASK is enabled. */
1557*61046927SAndroid Build Coastguard Worker    if (radv_image_is_tc_compat_cmask(image))
1558*61046927SAndroid Build Coastguard Worker       return RADV_FMASK_COMPRESSION_FULL;
1559*61046927SAndroid Build Coastguard Worker 
1560*61046927SAndroid Build Coastguard Worker    switch (layout) {
1561*61046927SAndroid Build Coastguard Worker    case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
1562*61046927SAndroid Build Coastguard Worker    case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
1563*61046927SAndroid Build Coastguard Worker       /* Don't compress images but no need to expand FMASK. */
1564*61046927SAndroid Build Coastguard Worker       return RADV_FMASK_COMPRESSION_PARTIAL;
1565*61046927SAndroid Build Coastguard Worker    case VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT:
1566*61046927SAndroid Build Coastguard Worker       /* Don't compress images that are in feedback loops. */
1567*61046927SAndroid Build Coastguard Worker       return RADV_FMASK_COMPRESSION_NONE;
1568*61046927SAndroid Build Coastguard Worker    default:
1569*61046927SAndroid Build Coastguard Worker       /* Don't compress images that are concurrent. */
1570*61046927SAndroid Build Coastguard Worker       return queue_mask == (1u << RADV_QUEUE_GENERAL) ? RADV_FMASK_COMPRESSION_FULL : RADV_FMASK_COMPRESSION_NONE;
1571*61046927SAndroid Build Coastguard Worker    }
1572*61046927SAndroid Build Coastguard Worker }
1573*61046927SAndroid Build Coastguard Worker 
1574*61046927SAndroid Build Coastguard Worker unsigned
radv_image_queue_family_mask(const struct radv_image * image,enum radv_queue_family family,enum radv_queue_family queue_family)1575*61046927SAndroid Build Coastguard Worker radv_image_queue_family_mask(const struct radv_image *image, enum radv_queue_family family,
1576*61046927SAndroid Build Coastguard Worker                              enum radv_queue_family queue_family)
1577*61046927SAndroid Build Coastguard Worker {
1578*61046927SAndroid Build Coastguard Worker    if (!image->exclusive)
1579*61046927SAndroid Build Coastguard Worker       return image->queue_family_mask;
1580*61046927SAndroid Build Coastguard Worker    if (family == RADV_QUEUE_FOREIGN)
1581*61046927SAndroid Build Coastguard Worker       return ((1u << RADV_MAX_QUEUE_FAMILIES) - 1u) | (1u << RADV_QUEUE_FOREIGN);
1582*61046927SAndroid Build Coastguard Worker    if (family == RADV_QUEUE_IGNORED)
1583*61046927SAndroid Build Coastguard Worker       return 1u << queue_family;
1584*61046927SAndroid Build Coastguard Worker    return 1u << family;
1585*61046927SAndroid Build Coastguard Worker }
1586*61046927SAndroid Build Coastguard Worker 
1587*61046927SAndroid Build Coastguard Worker bool
radv_image_is_renderable(const struct radv_device * device,const struct radv_image * image)1588*61046927SAndroid Build Coastguard Worker radv_image_is_renderable(const struct radv_device *device, const struct radv_image *image)
1589*61046927SAndroid Build Coastguard Worker {
1590*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
1591*61046927SAndroid Build Coastguard Worker 
1592*61046927SAndroid Build Coastguard Worker    if (image->vk.format == VK_FORMAT_R32G32B32_UINT || image->vk.format == VK_FORMAT_R32G32B32_SINT ||
1593*61046927SAndroid Build Coastguard Worker        image->vk.format == VK_FORMAT_R32G32B32_SFLOAT)
1594*61046927SAndroid Build Coastguard Worker       return false;
1595*61046927SAndroid Build Coastguard Worker 
1596*61046927SAndroid Build Coastguard Worker    if (pdev->info.gfx_level >= GFX9 && image->vk.image_type == VK_IMAGE_TYPE_3D &&
1597*61046927SAndroid Build Coastguard Worker        vk_format_get_blocksizebits(image->vk.format) == 128 && vk_format_is_compressed(image->vk.format))
1598*61046927SAndroid Build Coastguard Worker       return false;
1599*61046927SAndroid Build Coastguard Worker 
1600*61046927SAndroid Build Coastguard Worker    if (image->planes[0].surface.flags & RADEON_SURF_NO_RENDER_TARGET)
1601*61046927SAndroid Build Coastguard Worker       return false;
1602*61046927SAndroid Build Coastguard Worker 
1603*61046927SAndroid Build Coastguard Worker    return true;
1604*61046927SAndroid Build Coastguard Worker }
1605*61046927SAndroid Build Coastguard Worker 
1606*61046927SAndroid Build Coastguard Worker VKAPI_ATTR VkResult VKAPI_CALL
radv_CreateImage(VkDevice _device,const VkImageCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkImage * pImage)1607*61046927SAndroid Build Coastguard Worker radv_CreateImage(VkDevice _device, const VkImageCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
1608*61046927SAndroid Build Coastguard Worker                  VkImage *pImage)
1609*61046927SAndroid Build Coastguard Worker {
1610*61046927SAndroid Build Coastguard Worker #if DETECT_OS_ANDROID
1611*61046927SAndroid Build Coastguard Worker    const VkNativeBufferANDROID *gralloc_info = vk_find_struct_const(pCreateInfo->pNext, NATIVE_BUFFER_ANDROID);
1612*61046927SAndroid Build Coastguard Worker 
1613*61046927SAndroid Build Coastguard Worker    if (gralloc_info)
1614*61046927SAndroid Build Coastguard Worker       return radv_image_from_gralloc(_device, pCreateInfo, gralloc_info, pAllocator, pImage);
1615*61046927SAndroid Build Coastguard Worker #endif
1616*61046927SAndroid Build Coastguard Worker 
1617*61046927SAndroid Build Coastguard Worker #ifdef RADV_USE_WSI_PLATFORM
1618*61046927SAndroid Build Coastguard Worker    /* Ignore swapchain creation info on Android. Since we don't have an implementation in Mesa,
1619*61046927SAndroid Build Coastguard Worker     * we're guaranteed to access an Android object incorrectly.
1620*61046927SAndroid Build Coastguard Worker     */
1621*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(radv_device, device, _device);
1622*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
1623*61046927SAndroid Build Coastguard Worker    const VkImageSwapchainCreateInfoKHR *swapchain_info =
1624*61046927SAndroid Build Coastguard Worker       vk_find_struct_const(pCreateInfo->pNext, IMAGE_SWAPCHAIN_CREATE_INFO_KHR);
1625*61046927SAndroid Build Coastguard Worker    if (swapchain_info && swapchain_info->swapchain != VK_NULL_HANDLE) {
1626*61046927SAndroid Build Coastguard Worker       return wsi_common_create_swapchain_image(pdev->vk.wsi_device, pCreateInfo, swapchain_info->swapchain, pImage);
1627*61046927SAndroid Build Coastguard Worker    }
1628*61046927SAndroid Build Coastguard Worker #endif
1629*61046927SAndroid Build Coastguard Worker 
1630*61046927SAndroid Build Coastguard Worker    const struct wsi_image_create_info *wsi_info = vk_find_struct_const(pCreateInfo->pNext, WSI_IMAGE_CREATE_INFO_MESA);
1631*61046927SAndroid Build Coastguard Worker    bool scanout = wsi_info && wsi_info->scanout;
1632*61046927SAndroid Build Coastguard Worker    bool prime_blit_src = wsi_info && wsi_info->blit_src;
1633*61046927SAndroid Build Coastguard Worker 
1634*61046927SAndroid Build Coastguard Worker    return radv_image_create(_device,
1635*61046927SAndroid Build Coastguard Worker                             &(struct radv_image_create_info){
1636*61046927SAndroid Build Coastguard Worker                                .vk_info = pCreateInfo,
1637*61046927SAndroid Build Coastguard Worker                                .scanout = scanout,
1638*61046927SAndroid Build Coastguard Worker                                .prime_blit_src = prime_blit_src,
1639*61046927SAndroid Build Coastguard Worker                             },
1640*61046927SAndroid Build Coastguard Worker                             pAllocator, pImage, false);
1641*61046927SAndroid Build Coastguard Worker }
1642*61046927SAndroid Build Coastguard Worker 
1643*61046927SAndroid Build Coastguard Worker VKAPI_ATTR void VKAPI_CALL
radv_DestroyImage(VkDevice _device,VkImage _image,const VkAllocationCallbacks * pAllocator)1644*61046927SAndroid Build Coastguard Worker radv_DestroyImage(VkDevice _device, VkImage _image, const VkAllocationCallbacks *pAllocator)
1645*61046927SAndroid Build Coastguard Worker {
1646*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(radv_device, device, _device);
1647*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(radv_image, image, _image);
1648*61046927SAndroid Build Coastguard Worker 
1649*61046927SAndroid Build Coastguard Worker    if (!image)
1650*61046927SAndroid Build Coastguard Worker       return;
1651*61046927SAndroid Build Coastguard Worker 
1652*61046927SAndroid Build Coastguard Worker    radv_destroy_image(device, pAllocator, image);
1653*61046927SAndroid Build Coastguard Worker }
1654*61046927SAndroid Build Coastguard Worker 
1655*61046927SAndroid Build Coastguard Worker static void
radv_bind_image_memory(struct radv_device * device,struct radv_image * image,uint32_t bind_idx,struct radeon_winsys_bo * bo,uint64_t offset,uint64_t range)1656*61046927SAndroid Build Coastguard Worker radv_bind_image_memory(struct radv_device *device, struct radv_image *image, uint32_t bind_idx,
1657*61046927SAndroid Build Coastguard Worker                        struct radeon_winsys_bo *bo, uint64_t offset, uint64_t range)
1658*61046927SAndroid Build Coastguard Worker {
1659*61046927SAndroid Build Coastguard Worker    struct radv_physical_device *pdev = radv_device_physical(device);
1660*61046927SAndroid Build Coastguard Worker    struct radv_instance *instance = radv_physical_device_instance(pdev);
1661*61046927SAndroid Build Coastguard Worker 
1662*61046927SAndroid Build Coastguard Worker    assert(bind_idx < 3);
1663*61046927SAndroid Build Coastguard Worker 
1664*61046927SAndroid Build Coastguard Worker    image->bindings[bind_idx].bo = bo;
1665*61046927SAndroid Build Coastguard Worker    image->bindings[bind_idx].offset = offset;
1666*61046927SAndroid Build Coastguard Worker    image->bindings[bind_idx].bo_va = radv_buffer_get_va(bo);
1667*61046927SAndroid Build Coastguard Worker    image->bindings[bind_idx].range = range;
1668*61046927SAndroid Build Coastguard Worker 
1669*61046927SAndroid Build Coastguard Worker    radv_rmv_log_image_bind(device, bind_idx, radv_image_to_handle(image));
1670*61046927SAndroid Build Coastguard Worker 
1671*61046927SAndroid Build Coastguard Worker    vk_address_binding_report(&instance->vk, &image->vk.base,
1672*61046927SAndroid Build Coastguard Worker                              image->bindings[bind_idx].bo_va + image->bindings[bind_idx].offset,
1673*61046927SAndroid Build Coastguard Worker                              image->bindings[bind_idx].range, VK_DEVICE_ADDRESS_BINDING_TYPE_BIND_EXT);
1674*61046927SAndroid Build Coastguard Worker }
1675*61046927SAndroid Build Coastguard Worker 
1676*61046927SAndroid Build Coastguard Worker VKAPI_ATTR VkResult VKAPI_CALL
radv_BindImageMemory2(VkDevice _device,uint32_t bindInfoCount,const VkBindImageMemoryInfo * pBindInfos)1677*61046927SAndroid Build Coastguard Worker radv_BindImageMemory2(VkDevice _device, uint32_t bindInfoCount, const VkBindImageMemoryInfo *pBindInfos)
1678*61046927SAndroid Build Coastguard Worker {
1679*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(radv_device, device, _device);
1680*61046927SAndroid Build Coastguard Worker 
1681*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < bindInfoCount; ++i) {
1682*61046927SAndroid Build Coastguard Worker       VK_FROM_HANDLE(radv_device_memory, mem, pBindInfos[i].memory);
1683*61046927SAndroid Build Coastguard Worker       VK_FROM_HANDLE(radv_image, image, pBindInfos[i].image);
1684*61046927SAndroid Build Coastguard Worker       VkBindMemoryStatusKHR *status = (void *)vk_find_struct_const(&pBindInfos[i], BIND_MEMORY_STATUS_KHR);
1685*61046927SAndroid Build Coastguard Worker 
1686*61046927SAndroid Build Coastguard Worker       if (status)
1687*61046927SAndroid Build Coastguard Worker          *status->pResult = VK_SUCCESS;
1688*61046927SAndroid Build Coastguard Worker 
1689*61046927SAndroid Build Coastguard Worker          /* Ignore this struct on Android, we cannot access swapchain structures there. */
1690*61046927SAndroid Build Coastguard Worker #ifdef RADV_USE_WSI_PLATFORM
1691*61046927SAndroid Build Coastguard Worker       const VkBindImageMemorySwapchainInfoKHR *swapchain_info =
1692*61046927SAndroid Build Coastguard Worker          vk_find_struct_const(pBindInfos[i].pNext, BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR);
1693*61046927SAndroid Build Coastguard Worker 
1694*61046927SAndroid Build Coastguard Worker       if (swapchain_info && swapchain_info->swapchain != VK_NULL_HANDLE) {
1695*61046927SAndroid Build Coastguard Worker          struct radv_image *swapchain_img =
1696*61046927SAndroid Build Coastguard Worker             radv_image_from_handle(wsi_common_get_image(swapchain_info->swapchain, swapchain_info->imageIndex));
1697*61046927SAndroid Build Coastguard Worker 
1698*61046927SAndroid Build Coastguard Worker          radv_bind_image_memory(device, image, 0,
1699*61046927SAndroid Build Coastguard Worker                                 swapchain_img->bindings[0].bo, swapchain_img->bindings[0].offset,
1700*61046927SAndroid Build Coastguard Worker                                 swapchain_img->bindings[0].range);
1701*61046927SAndroid Build Coastguard Worker          continue;
1702*61046927SAndroid Build Coastguard Worker       }
1703*61046927SAndroid Build Coastguard Worker #endif
1704*61046927SAndroid Build Coastguard Worker 
1705*61046927SAndroid Build Coastguard Worker       const VkBindImagePlaneMemoryInfo *plane_info = NULL;
1706*61046927SAndroid Build Coastguard Worker       uint32_t bind_idx = 0;
1707*61046927SAndroid Build Coastguard Worker 
1708*61046927SAndroid Build Coastguard Worker       if (image->disjoint) {
1709*61046927SAndroid Build Coastguard Worker          plane_info = vk_find_struct_const(pBindInfos[i].pNext, BIND_IMAGE_PLANE_MEMORY_INFO);
1710*61046927SAndroid Build Coastguard Worker          bind_idx = radv_plane_from_aspect(plane_info->planeAspect);
1711*61046927SAndroid Build Coastguard Worker       }
1712*61046927SAndroid Build Coastguard Worker 
1713*61046927SAndroid Build Coastguard Worker       VkImagePlaneMemoryRequirementsInfo plane = {
1714*61046927SAndroid Build Coastguard Worker          .sType = VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO,
1715*61046927SAndroid Build Coastguard Worker          .planeAspect = plane_info ? plane_info->planeAspect : 0,
1716*61046927SAndroid Build Coastguard Worker       };
1717*61046927SAndroid Build Coastguard Worker       VkImageMemoryRequirementsInfo2 info = {
1718*61046927SAndroid Build Coastguard Worker          .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
1719*61046927SAndroid Build Coastguard Worker          .pNext = image->disjoint ? &plane : NULL,
1720*61046927SAndroid Build Coastguard Worker          .image = pBindInfos[i].image,
1721*61046927SAndroid Build Coastguard Worker       };
1722*61046927SAndroid Build Coastguard Worker       VkMemoryRequirements2 reqs = {
1723*61046927SAndroid Build Coastguard Worker          .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
1724*61046927SAndroid Build Coastguard Worker       };
1725*61046927SAndroid Build Coastguard Worker 
1726*61046927SAndroid Build Coastguard Worker       radv_GetImageMemoryRequirements2(_device, &info, &reqs);
1727*61046927SAndroid Build Coastguard Worker 
1728*61046927SAndroid Build Coastguard Worker       if (mem->alloc_size) {
1729*61046927SAndroid Build Coastguard Worker          if (pBindInfos[i].memoryOffset + reqs.memoryRequirements.size > mem->alloc_size) {
1730*61046927SAndroid Build Coastguard Worker             if (status)
1731*61046927SAndroid Build Coastguard Worker                *status->pResult = VK_ERROR_UNKNOWN;
1732*61046927SAndroid Build Coastguard Worker             return vk_errorf(device, VK_ERROR_UNKNOWN, "Device memory object too small for the image.\n");
1733*61046927SAndroid Build Coastguard Worker          }
1734*61046927SAndroid Build Coastguard Worker       }
1735*61046927SAndroid Build Coastguard Worker 
1736*61046927SAndroid Build Coastguard Worker       radv_bind_image_memory(device, image, bind_idx, mem->bo, pBindInfos[i].memoryOffset,
1737*61046927SAndroid Build Coastguard Worker                              reqs.memoryRequirements.size);
1738*61046927SAndroid Build Coastguard Worker    }
1739*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
1740*61046927SAndroid Build Coastguard Worker }
1741*61046927SAndroid Build Coastguard Worker 
1742*61046927SAndroid Build Coastguard Worker VKAPI_ATTR void VKAPI_CALL
radv_GetImageSubresourceLayout2KHR(VkDevice _device,VkImage _image,const VkImageSubresource2KHR * pSubresource,VkSubresourceLayout2KHR * pLayout)1743*61046927SAndroid Build Coastguard Worker radv_GetImageSubresourceLayout2KHR(VkDevice _device, VkImage _image, const VkImageSubresource2KHR *pSubresource,
1744*61046927SAndroid Build Coastguard Worker                                    VkSubresourceLayout2KHR *pLayout)
1745*61046927SAndroid Build Coastguard Worker {
1746*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(radv_image, image, _image);
1747*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(radv_device, device, _device);
1748*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
1749*61046927SAndroid Build Coastguard Worker    int level = pSubresource->imageSubresource.mipLevel;
1750*61046927SAndroid Build Coastguard Worker    int layer = pSubresource->imageSubresource.arrayLayer;
1751*61046927SAndroid Build Coastguard Worker 
1752*61046927SAndroid Build Coastguard Worker    const unsigned plane_count = vk_format_get_plane_count(image->vk.format);
1753*61046927SAndroid Build Coastguard Worker    unsigned plane_id = 0;
1754*61046927SAndroid Build Coastguard Worker    if (plane_count > 1)
1755*61046927SAndroid Build Coastguard Worker       plane_id = radv_plane_from_aspect(pSubresource->imageSubresource.aspectMask);
1756*61046927SAndroid Build Coastguard Worker 
1757*61046927SAndroid Build Coastguard Worker    struct radv_image_plane *plane = &image->planes[plane_id];
1758*61046927SAndroid Build Coastguard Worker    struct radeon_surf *surface = &plane->surface;
1759*61046927SAndroid Build Coastguard Worker 
1760*61046927SAndroid Build Coastguard Worker    if (image->vk.tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT && plane_count == 1) {
1761*61046927SAndroid Build Coastguard Worker       unsigned mem_plane_id = radv_plane_from_aspect(pSubresource->imageSubresource.aspectMask);
1762*61046927SAndroid Build Coastguard Worker 
1763*61046927SAndroid Build Coastguard Worker       assert(level == 0);
1764*61046927SAndroid Build Coastguard Worker       assert(layer == 0);
1765*61046927SAndroid Build Coastguard Worker 
1766*61046927SAndroid Build Coastguard Worker       pLayout->subresourceLayout.offset = ac_surface_get_plane_offset(pdev->info.gfx_level, surface, mem_plane_id, 0);
1767*61046927SAndroid Build Coastguard Worker       pLayout->subresourceLayout.rowPitch =
1768*61046927SAndroid Build Coastguard Worker          ac_surface_get_plane_stride(pdev->info.gfx_level, surface, mem_plane_id, level);
1769*61046927SAndroid Build Coastguard Worker       pLayout->subresourceLayout.arrayPitch = 0;
1770*61046927SAndroid Build Coastguard Worker       pLayout->subresourceLayout.depthPitch = 0;
1771*61046927SAndroid Build Coastguard Worker       pLayout->subresourceLayout.size = ac_surface_get_plane_size(surface, mem_plane_id);
1772*61046927SAndroid Build Coastguard Worker    } else if (pdev->info.gfx_level >= GFX9) {
1773*61046927SAndroid Build Coastguard Worker       uint64_t level_offset = surface->is_linear ? surface->u.gfx9.offset[level] : 0;
1774*61046927SAndroid Build Coastguard Worker 
1775*61046927SAndroid Build Coastguard Worker       pLayout->subresourceLayout.offset =
1776*61046927SAndroid Build Coastguard Worker          ac_surface_get_plane_offset(pdev->info.gfx_level, &plane->surface, 0, layer) + level_offset;
1777*61046927SAndroid Build Coastguard Worker       if (image->vk.format == VK_FORMAT_R32G32B32_UINT || image->vk.format == VK_FORMAT_R32G32B32_SINT ||
1778*61046927SAndroid Build Coastguard Worker           image->vk.format == VK_FORMAT_R32G32B32_SFLOAT) {
1779*61046927SAndroid Build Coastguard Worker          /* Adjust the number of bytes between each row because
1780*61046927SAndroid Build Coastguard Worker           * the pitch is actually the number of components per
1781*61046927SAndroid Build Coastguard Worker           * row.
1782*61046927SAndroid Build Coastguard Worker           */
1783*61046927SAndroid Build Coastguard Worker          pLayout->subresourceLayout.rowPitch = surface->u.gfx9.surf_pitch * surface->bpe / 3;
1784*61046927SAndroid Build Coastguard Worker       } else {
1785*61046927SAndroid Build Coastguard Worker          uint32_t pitch = surface->is_linear ? surface->u.gfx9.pitch[level] : surface->u.gfx9.surf_pitch;
1786*61046927SAndroid Build Coastguard Worker 
1787*61046927SAndroid Build Coastguard Worker          assert(util_is_power_of_two_nonzero(surface->bpe));
1788*61046927SAndroid Build Coastguard Worker          pLayout->subresourceLayout.rowPitch = pitch * surface->bpe;
1789*61046927SAndroid Build Coastguard Worker       }
1790*61046927SAndroid Build Coastguard Worker 
1791*61046927SAndroid Build Coastguard Worker       pLayout->subresourceLayout.arrayPitch = surface->u.gfx9.surf_slice_size;
1792*61046927SAndroid Build Coastguard Worker       pLayout->subresourceLayout.depthPitch = surface->u.gfx9.surf_slice_size;
1793*61046927SAndroid Build Coastguard Worker       pLayout->subresourceLayout.size = surface->u.gfx9.surf_slice_size;
1794*61046927SAndroid Build Coastguard Worker       if (image->vk.image_type == VK_IMAGE_TYPE_3D)
1795*61046927SAndroid Build Coastguard Worker          pLayout->subresourceLayout.size *= u_minify(image->vk.extent.depth, level);
1796*61046927SAndroid Build Coastguard Worker    } else {
1797*61046927SAndroid Build Coastguard Worker       pLayout->subresourceLayout.offset = (uint64_t)surface->u.legacy.level[level].offset_256B * 256 +
1798*61046927SAndroid Build Coastguard Worker                                           (uint64_t)surface->u.legacy.level[level].slice_size_dw * 4 * layer;
1799*61046927SAndroid Build Coastguard Worker       pLayout->subresourceLayout.rowPitch = surface->u.legacy.level[level].nblk_x * surface->bpe;
1800*61046927SAndroid Build Coastguard Worker       pLayout->subresourceLayout.arrayPitch = (uint64_t)surface->u.legacy.level[level].slice_size_dw * 4;
1801*61046927SAndroid Build Coastguard Worker       pLayout->subresourceLayout.depthPitch = (uint64_t)surface->u.legacy.level[level].slice_size_dw * 4;
1802*61046927SAndroid Build Coastguard Worker       pLayout->subresourceLayout.size = (uint64_t)surface->u.legacy.level[level].slice_size_dw * 4;
1803*61046927SAndroid Build Coastguard Worker       if (image->vk.image_type == VK_IMAGE_TYPE_3D)
1804*61046927SAndroid Build Coastguard Worker          pLayout->subresourceLayout.size *= u_minify(image->vk.extent.depth, level);
1805*61046927SAndroid Build Coastguard Worker    }
1806*61046927SAndroid Build Coastguard Worker 
1807*61046927SAndroid Build Coastguard Worker    VkImageCompressionPropertiesEXT *image_compression_props =
1808*61046927SAndroid Build Coastguard Worker       vk_find_struct(pLayout->pNext, IMAGE_COMPRESSION_PROPERTIES_EXT);
1809*61046927SAndroid Build Coastguard Worker    if (image_compression_props) {
1810*61046927SAndroid Build Coastguard Worker       image_compression_props->imageCompressionFixedRateFlags = VK_IMAGE_COMPRESSION_FIXED_RATE_NONE_EXT;
1811*61046927SAndroid Build Coastguard Worker 
1812*61046927SAndroid Build Coastguard Worker       if (image->vk.aspects & VK_IMAGE_ASPECT_DEPTH_BIT) {
1813*61046927SAndroid Build Coastguard Worker          image_compression_props->imageCompressionFlags =
1814*61046927SAndroid Build Coastguard Worker             radv_image_has_htile(image) ? VK_IMAGE_COMPRESSION_DEFAULT_EXT : VK_IMAGE_COMPRESSION_DISABLED_EXT;
1815*61046927SAndroid Build Coastguard Worker       } else {
1816*61046927SAndroid Build Coastguard Worker          image_compression_props->imageCompressionFlags =
1817*61046927SAndroid Build Coastguard Worker             radv_image_has_dcc(image) ? VK_IMAGE_COMPRESSION_DEFAULT_EXT : VK_IMAGE_COMPRESSION_DISABLED_EXT;
1818*61046927SAndroid Build Coastguard Worker       }
1819*61046927SAndroid Build Coastguard Worker    }
1820*61046927SAndroid Build Coastguard Worker }
1821*61046927SAndroid Build Coastguard Worker 
1822*61046927SAndroid Build Coastguard Worker VKAPI_ATTR VkResult VKAPI_CALL
radv_GetImageDrmFormatModifierPropertiesEXT(VkDevice _device,VkImage _image,VkImageDrmFormatModifierPropertiesEXT * pProperties)1823*61046927SAndroid Build Coastguard Worker radv_GetImageDrmFormatModifierPropertiesEXT(VkDevice _device, VkImage _image,
1824*61046927SAndroid Build Coastguard Worker                                             VkImageDrmFormatModifierPropertiesEXT *pProperties)
1825*61046927SAndroid Build Coastguard Worker {
1826*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(radv_image, image, _image);
1827*61046927SAndroid Build Coastguard Worker 
1828*61046927SAndroid Build Coastguard Worker    pProperties->drmFormatModifier = image->planes[0].surface.modifier;
1829*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
1830*61046927SAndroid Build Coastguard Worker }
1831