xref: /aosp_15_r20/external/mesa3d/src/nouveau/vulkan/nvk_image.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright © 2022 Collabora Ltd. and Red Hat Inc.
3*61046927SAndroid Build Coastguard Worker  * SPDX-License-Identifier: MIT
4*61046927SAndroid Build Coastguard Worker  */
5*61046927SAndroid Build Coastguard Worker #include "nvk_image.h"
6*61046927SAndroid Build Coastguard Worker 
7*61046927SAndroid Build Coastguard Worker #include "nvk_device.h"
8*61046927SAndroid Build Coastguard Worker #include "nvk_device_memory.h"
9*61046927SAndroid Build Coastguard Worker #include "nvk_entrypoints.h"
10*61046927SAndroid Build Coastguard Worker #include "nvk_format.h"
11*61046927SAndroid Build Coastguard Worker #include "nvk_physical_device.h"
12*61046927SAndroid Build Coastguard Worker #include "nvkmd/nvkmd.h"
13*61046927SAndroid Build Coastguard Worker 
14*61046927SAndroid Build Coastguard Worker #include "vk_enum_to_str.h"
15*61046927SAndroid Build Coastguard Worker #include "vk_format.h"
16*61046927SAndroid Build Coastguard Worker #include "nil.h"
17*61046927SAndroid Build Coastguard Worker #include "vk_enum_defines.h"
18*61046927SAndroid Build Coastguard Worker #include "vk_format.h"
19*61046927SAndroid Build Coastguard Worker 
20*61046927SAndroid Build Coastguard Worker #include "clb097.h"
21*61046927SAndroid Build Coastguard Worker #include "clb197.h"
22*61046927SAndroid Build Coastguard Worker #include "clc097.h"
23*61046927SAndroid Build Coastguard Worker #include "clc597.h"
24*61046927SAndroid Build Coastguard Worker 
25*61046927SAndroid Build Coastguard Worker static VkFormatFeatureFlags2
nvk_get_image_plane_format_features(struct nvk_physical_device * pdev,VkFormat vk_format,VkImageTiling tiling,uint64_t drm_format_mod)26*61046927SAndroid Build Coastguard Worker nvk_get_image_plane_format_features(struct nvk_physical_device *pdev,
27*61046927SAndroid Build Coastguard Worker                                     VkFormat vk_format, VkImageTiling tiling,
28*61046927SAndroid Build Coastguard Worker                                     uint64_t drm_format_mod)
29*61046927SAndroid Build Coastguard Worker {
30*61046927SAndroid Build Coastguard Worker    VkFormatFeatureFlags2 features = 0;
31*61046927SAndroid Build Coastguard Worker 
32*61046927SAndroid Build Coastguard Worker    if (tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT &&
33*61046927SAndroid Build Coastguard Worker        drm_format_mod != DRM_FORMAT_MOD_LINEAR &&
34*61046927SAndroid Build Coastguard Worker        !fourcc_mod_is_vendor(drm_format_mod, NVIDIA))
35*61046927SAndroid Build Coastguard Worker       return 0;
36*61046927SAndroid Build Coastguard Worker 
37*61046927SAndroid Build Coastguard Worker    enum pipe_format p_format = vk_format_to_pipe_format(vk_format);
38*61046927SAndroid Build Coastguard Worker    if (p_format == PIPE_FORMAT_NONE)
39*61046927SAndroid Build Coastguard Worker       return 0;
40*61046927SAndroid Build Coastguard Worker 
41*61046927SAndroid Build Coastguard Worker    /* You can't tile a non-power-of-two */
42*61046927SAndroid Build Coastguard Worker    if (!util_is_power_of_two_nonzero(util_format_get_blocksize(p_format)))
43*61046927SAndroid Build Coastguard Worker       return 0;
44*61046927SAndroid Build Coastguard Worker 
45*61046927SAndroid Build Coastguard Worker    if (nil_format_supports_texturing(&pdev->info, p_format)) {
46*61046927SAndroid Build Coastguard Worker       features |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT;
47*61046927SAndroid Build Coastguard Worker       features |= VK_FORMAT_FEATURE_2_BLIT_SRC_BIT;
48*61046927SAndroid Build Coastguard Worker    }
49*61046927SAndroid Build Coastguard Worker 
50*61046927SAndroid Build Coastguard Worker    if (nil_format_supports_filtering(&pdev->info, p_format)) {
51*61046927SAndroid Build Coastguard Worker       features |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
52*61046927SAndroid Build Coastguard Worker       if (pdev->info.cls_eng3d >= MAXWELL_B)
53*61046927SAndroid Build Coastguard Worker          features |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_MINMAX_BIT;
54*61046927SAndroid Build Coastguard Worker    }
55*61046927SAndroid Build Coastguard Worker 
56*61046927SAndroid Build Coastguard Worker    /* TODO: VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT */
57*61046927SAndroid Build Coastguard Worker    if (vk_format_has_depth(vk_format)) {
58*61046927SAndroid Build Coastguard Worker       features |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT;
59*61046927SAndroid Build Coastguard Worker    }
60*61046927SAndroid Build Coastguard Worker 
61*61046927SAndroid Build Coastguard Worker    if (nil_format_supports_color_targets(&pdev->info, p_format) &&
62*61046927SAndroid Build Coastguard Worker        tiling != VK_IMAGE_TILING_LINEAR) {
63*61046927SAndroid Build Coastguard Worker       features |= VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT;
64*61046927SAndroid Build Coastguard Worker       if (nil_format_supports_blending(&pdev->info, p_format))
65*61046927SAndroid Build Coastguard Worker          features |= VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BLEND_BIT;
66*61046927SAndroid Build Coastguard Worker       features |= VK_FORMAT_FEATURE_2_BLIT_DST_BIT;
67*61046927SAndroid Build Coastguard Worker    }
68*61046927SAndroid Build Coastguard Worker 
69*61046927SAndroid Build Coastguard Worker    if (vk_format_is_depth_or_stencil(vk_format)) {
70*61046927SAndroid Build Coastguard Worker       if (!nil_format_supports_depth_stencil(&pdev->info, p_format) ||
71*61046927SAndroid Build Coastguard Worker           tiling == VK_IMAGE_TILING_LINEAR)
72*61046927SAndroid Build Coastguard Worker          return 0;
73*61046927SAndroid Build Coastguard Worker 
74*61046927SAndroid Build Coastguard Worker       features |= VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT;
75*61046927SAndroid Build Coastguard Worker    }
76*61046927SAndroid Build Coastguard Worker 
77*61046927SAndroid Build Coastguard Worker    if (nil_format_supports_storage(&pdev->info, p_format)) {
78*61046927SAndroid Build Coastguard Worker       features |= VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT |
79*61046927SAndroid Build Coastguard Worker                   VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT;
80*61046927SAndroid Build Coastguard Worker       if (pdev->info.cls_eng3d >= MAXWELL_A)
81*61046927SAndroid Build Coastguard Worker          features |= VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT;
82*61046927SAndroid Build Coastguard Worker    }
83*61046927SAndroid Build Coastguard Worker 
84*61046927SAndroid Build Coastguard Worker    if (p_format == PIPE_FORMAT_R32_UINT || p_format == PIPE_FORMAT_R32_SINT ||
85*61046927SAndroid Build Coastguard Worker        p_format == PIPE_FORMAT_R64_UINT || p_format == PIPE_FORMAT_R64_SINT)
86*61046927SAndroid Build Coastguard Worker       features |= VK_FORMAT_FEATURE_2_STORAGE_IMAGE_ATOMIC_BIT;
87*61046927SAndroid Build Coastguard Worker 
88*61046927SAndroid Build Coastguard Worker    if (features != 0) {
89*61046927SAndroid Build Coastguard Worker       features |= VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT;
90*61046927SAndroid Build Coastguard Worker       features |= VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT;
91*61046927SAndroid Build Coastguard Worker    }
92*61046927SAndroid Build Coastguard Worker 
93*61046927SAndroid Build Coastguard Worker    return features;
94*61046927SAndroid Build Coastguard Worker }
95*61046927SAndroid Build Coastguard Worker 
96*61046927SAndroid Build Coastguard Worker VkFormatFeatureFlags2
nvk_get_image_format_features(struct nvk_physical_device * pdev,VkFormat vk_format,VkImageTiling tiling,uint64_t drm_format_mod)97*61046927SAndroid Build Coastguard Worker nvk_get_image_format_features(struct nvk_physical_device *pdev,
98*61046927SAndroid Build Coastguard Worker                               VkFormat vk_format, VkImageTiling tiling,
99*61046927SAndroid Build Coastguard Worker                               uint64_t drm_format_mod)
100*61046927SAndroid Build Coastguard Worker {
101*61046927SAndroid Build Coastguard Worker    const struct vk_format_ycbcr_info *ycbcr_info =
102*61046927SAndroid Build Coastguard Worker          vk_format_get_ycbcr_info(vk_format);
103*61046927SAndroid Build Coastguard Worker    if (ycbcr_info == NULL) {
104*61046927SAndroid Build Coastguard Worker       return nvk_get_image_plane_format_features(pdev, vk_format, tiling,
105*61046927SAndroid Build Coastguard Worker                                                  drm_format_mod);
106*61046927SAndroid Build Coastguard Worker    }
107*61046927SAndroid Build Coastguard Worker 
108*61046927SAndroid Build Coastguard Worker    /* For multi-plane, we get the feature flags of each plane separately,
109*61046927SAndroid Build Coastguard Worker     * then take their intersection as the overall format feature flags
110*61046927SAndroid Build Coastguard Worker     */
111*61046927SAndroid Build Coastguard Worker    VkFormatFeatureFlags2 features = ~0ull;
112*61046927SAndroid Build Coastguard Worker    bool cosited_chroma = false;
113*61046927SAndroid Build Coastguard Worker    for (uint8_t plane = 0; plane < ycbcr_info->n_planes; plane++) {
114*61046927SAndroid Build Coastguard Worker       const struct vk_format_ycbcr_plane *plane_info = &ycbcr_info->planes[plane];
115*61046927SAndroid Build Coastguard Worker       features &= nvk_get_image_plane_format_features(pdev, plane_info->format,
116*61046927SAndroid Build Coastguard Worker                                                       tiling, drm_format_mod);
117*61046927SAndroid Build Coastguard Worker       if (plane_info->denominator_scales[0] > 1 ||
118*61046927SAndroid Build Coastguard Worker           plane_info->denominator_scales[1] > 1)
119*61046927SAndroid Build Coastguard Worker          cosited_chroma = true;
120*61046927SAndroid Build Coastguard Worker    }
121*61046927SAndroid Build Coastguard Worker    if (features == 0)
122*61046927SAndroid Build Coastguard Worker       return 0;
123*61046927SAndroid Build Coastguard Worker 
124*61046927SAndroid Build Coastguard Worker    /* Uh... We really should be able to sample from YCbCr */
125*61046927SAndroid Build Coastguard Worker    assert(features & VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT);
126*61046927SAndroid Build Coastguard Worker    assert(features & VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_LINEAR_BIT);
127*61046927SAndroid Build Coastguard Worker 
128*61046927SAndroid Build Coastguard Worker    /* These aren't allowed for YCbCr formats */
129*61046927SAndroid Build Coastguard Worker    features &= ~(VK_FORMAT_FEATURE_2_BLIT_SRC_BIT |
130*61046927SAndroid Build Coastguard Worker                  VK_FORMAT_FEATURE_2_BLIT_DST_BIT |
131*61046927SAndroid Build Coastguard Worker                  VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT |
132*61046927SAndroid Build Coastguard Worker                  VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BLEND_BIT |
133*61046927SAndroid Build Coastguard Worker                  VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT);
134*61046927SAndroid Build Coastguard Worker 
135*61046927SAndroid Build Coastguard Worker    /* This is supported on all YCbCr formats */
136*61046927SAndroid Build Coastguard Worker    features |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT;
137*61046927SAndroid Build Coastguard Worker 
138*61046927SAndroid Build Coastguard Worker    if (ycbcr_info->n_planes > 1) {
139*61046927SAndroid Build Coastguard Worker       /* DISJOINT_BIT implies that each plane has its own separate binding,
140*61046927SAndroid Build Coastguard Worker        * while SEPARATE_RECONSTRUCTION_FILTER_BIT implies that luma and chroma
141*61046927SAndroid Build Coastguard Worker        * each have their own, separate filters, so these two bits make sense
142*61046927SAndroid Build Coastguard Worker        * for multi-planar formats only.
143*61046927SAndroid Build Coastguard Worker        *
144*61046927SAndroid Build Coastguard Worker        * For MIDPOINT_CHROMA_SAMPLES_BIT, NVIDIA HW on single-plane interleaved
145*61046927SAndroid Build Coastguard Worker        * YCbCr defaults to COSITED_EVEN, which is inaccurate and fails tests.
146*61046927SAndroid Build Coastguard Worker        * This can be fixed with a NIR tweak but for now, we only enable this bit
147*61046927SAndroid Build Coastguard Worker        * for multi-plane formats. See Issue #9525 on the mesa/main tracker.
148*61046927SAndroid Build Coastguard Worker        */
149*61046927SAndroid Build Coastguard Worker       features |= VK_FORMAT_FEATURE_DISJOINT_BIT |
150*61046927SAndroid Build Coastguard Worker                   VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT |
151*61046927SAndroid Build Coastguard Worker                   VK_FORMAT_FEATURE_2_MIDPOINT_CHROMA_SAMPLES_BIT;
152*61046927SAndroid Build Coastguard Worker    }
153*61046927SAndroid Build Coastguard Worker 
154*61046927SAndroid Build Coastguard Worker    if (cosited_chroma)
155*61046927SAndroid Build Coastguard Worker       features |= VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT;
156*61046927SAndroid Build Coastguard Worker 
157*61046927SAndroid Build Coastguard Worker    return features;
158*61046927SAndroid Build Coastguard Worker }
159*61046927SAndroid Build Coastguard Worker 
160*61046927SAndroid Build Coastguard Worker void
nvk_get_drm_format_modifier_properties_list(struct nvk_physical_device * pdev,VkFormat vk_format,VkBaseOutStructure * ext)161*61046927SAndroid Build Coastguard Worker nvk_get_drm_format_modifier_properties_list(struct nvk_physical_device *pdev,
162*61046927SAndroid Build Coastguard Worker                                             VkFormat vk_format,
163*61046927SAndroid Build Coastguard Worker                                             VkBaseOutStructure *ext)
164*61046927SAndroid Build Coastguard Worker {
165*61046927SAndroid Build Coastguard Worker    assert(ext->sType == VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT ||
166*61046927SAndroid Build Coastguard Worker           ext->sType == VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_2_EXT);
167*61046927SAndroid Build Coastguard Worker 
168*61046927SAndroid Build Coastguard Worker    /* The two top-level data structures are the same.  It's only when
169*61046927SAndroid Build Coastguard Worker     * you get to walking the actual list of modifier properties that
170*61046927SAndroid Build Coastguard Worker     * they differ.
171*61046927SAndroid Build Coastguard Worker     */
172*61046927SAndroid Build Coastguard Worker    VkDrmFormatModifierPropertiesListEXT *p = (void *)ext;
173*61046927SAndroid Build Coastguard Worker 
174*61046927SAndroid Build Coastguard Worker    /* We don't support modifiers for YCbCr images */
175*61046927SAndroid Build Coastguard Worker    if (vk_format_get_ycbcr_info(vk_format) != NULL) {
176*61046927SAndroid Build Coastguard Worker       p->drmFormatModifierCount = 0;
177*61046927SAndroid Build Coastguard Worker       return;
178*61046927SAndroid Build Coastguard Worker    }
179*61046927SAndroid Build Coastguard Worker 
180*61046927SAndroid Build Coastguard Worker    /* Check that we actually support the format so we don't try to query
181*61046927SAndroid Build Coastguard Worker     * modifiers for formats NIL doesn't support.
182*61046927SAndroid Build Coastguard Worker     */
183*61046927SAndroid Build Coastguard Worker    const VkFormatFeatureFlags2 tiled_features =
184*61046927SAndroid Build Coastguard Worker       nvk_get_image_plane_format_features(pdev, vk_format,
185*61046927SAndroid Build Coastguard Worker                                           VK_IMAGE_TILING_OPTIMAL,
186*61046927SAndroid Build Coastguard Worker                                           DRM_FORMAT_MOD_INVALID);
187*61046927SAndroid Build Coastguard Worker    if (tiled_features == 0) {
188*61046927SAndroid Build Coastguard Worker       p->drmFormatModifierCount = 0;
189*61046927SAndroid Build Coastguard Worker       return;
190*61046927SAndroid Build Coastguard Worker    }
191*61046927SAndroid Build Coastguard Worker 
192*61046927SAndroid Build Coastguard Worker    uint64_t mods[NIL_MAX_DRM_FORMAT_MODS];
193*61046927SAndroid Build Coastguard Worker    size_t mod_count = NIL_MAX_DRM_FORMAT_MODS;
194*61046927SAndroid Build Coastguard Worker    enum pipe_format p_format = vk_format_to_pipe_format(vk_format);
195*61046927SAndroid Build Coastguard Worker    nil_drm_format_mods_for_format(&pdev->info, nil_format(p_format),
196*61046927SAndroid Build Coastguard Worker                                   &mod_count, &mods);
197*61046927SAndroid Build Coastguard Worker    if (mod_count == 0) {
198*61046927SAndroid Build Coastguard Worker       p->drmFormatModifierCount = 0;
199*61046927SAndroid Build Coastguard Worker       return;
200*61046927SAndroid Build Coastguard Worker    }
201*61046927SAndroid Build Coastguard Worker 
202*61046927SAndroid Build Coastguard Worker    switch (ext->sType) {
203*61046927SAndroid Build Coastguard Worker    case VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT: {
204*61046927SAndroid Build Coastguard Worker       VK_OUTARRAY_MAKE_TYPED(VkDrmFormatModifierPropertiesEXT, out,
205*61046927SAndroid Build Coastguard Worker                              p->pDrmFormatModifierProperties,
206*61046927SAndroid Build Coastguard Worker                              &p->drmFormatModifierCount);
207*61046927SAndroid Build Coastguard Worker 
208*61046927SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < mod_count; i++) {
209*61046927SAndroid Build Coastguard Worker          const VkFormatFeatureFlags2 features2 =
210*61046927SAndroid Build Coastguard Worker             nvk_get_image_format_features(pdev, vk_format,
211*61046927SAndroid Build Coastguard Worker                                           VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT,
212*61046927SAndroid Build Coastguard Worker                                           mods[i]);
213*61046927SAndroid Build Coastguard Worker          if (features2 != 0) {
214*61046927SAndroid Build Coastguard Worker             vk_outarray_append_typed(VkDrmFormatModifierPropertiesEXT, &out, mp) {
215*61046927SAndroid Build Coastguard Worker                mp->drmFormatModifier = mods[i];
216*61046927SAndroid Build Coastguard Worker                mp->drmFormatModifierPlaneCount = 1;
217*61046927SAndroid Build Coastguard Worker                mp->drmFormatModifierTilingFeatures =
218*61046927SAndroid Build Coastguard Worker                   vk_format_features2_to_features(features2);
219*61046927SAndroid Build Coastguard Worker             }
220*61046927SAndroid Build Coastguard Worker          }
221*61046927SAndroid Build Coastguard Worker       }
222*61046927SAndroid Build Coastguard Worker       break;
223*61046927SAndroid Build Coastguard Worker    }
224*61046927SAndroid Build Coastguard Worker 
225*61046927SAndroid Build Coastguard Worker    case VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_2_EXT: {
226*61046927SAndroid Build Coastguard Worker       VkDrmFormatModifierPropertiesList2EXT *p2 = (void *)p;
227*61046927SAndroid Build Coastguard Worker       VK_OUTARRAY_MAKE_TYPED(VkDrmFormatModifierProperties2EXT, out,
228*61046927SAndroid Build Coastguard Worker                              p2->pDrmFormatModifierProperties,
229*61046927SAndroid Build Coastguard Worker                              &p2->drmFormatModifierCount);
230*61046927SAndroid Build Coastguard Worker 
231*61046927SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < mod_count; i++) {
232*61046927SAndroid Build Coastguard Worker          const VkFormatFeatureFlags2 features2 =
233*61046927SAndroid Build Coastguard Worker             nvk_get_image_format_features(pdev, vk_format,
234*61046927SAndroid Build Coastguard Worker                                           VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT,
235*61046927SAndroid Build Coastguard Worker                                           mods[i]);
236*61046927SAndroid Build Coastguard Worker          if (features2 != 0) {
237*61046927SAndroid Build Coastguard Worker             vk_outarray_append_typed(VkDrmFormatModifierProperties2EXT, &out, mp) {
238*61046927SAndroid Build Coastguard Worker                mp->drmFormatModifier = mods[i];
239*61046927SAndroid Build Coastguard Worker                mp->drmFormatModifierPlaneCount = 1;
240*61046927SAndroid Build Coastguard Worker                mp->drmFormatModifierTilingFeatures = features2;
241*61046927SAndroid Build Coastguard Worker             }
242*61046927SAndroid Build Coastguard Worker          }
243*61046927SAndroid Build Coastguard Worker       }
244*61046927SAndroid Build Coastguard Worker       break;
245*61046927SAndroid Build Coastguard Worker    }
246*61046927SAndroid Build Coastguard Worker 
247*61046927SAndroid Build Coastguard Worker    default:
248*61046927SAndroid Build Coastguard Worker       unreachable("Invalid structure type");
249*61046927SAndroid Build Coastguard Worker    }
250*61046927SAndroid Build Coastguard Worker }
251*61046927SAndroid Build Coastguard Worker 
252*61046927SAndroid Build Coastguard Worker static VkFormatFeatureFlags2
vk_image_usage_to_format_features(VkImageUsageFlagBits usage_flag)253*61046927SAndroid Build Coastguard Worker vk_image_usage_to_format_features(VkImageUsageFlagBits usage_flag)
254*61046927SAndroid Build Coastguard Worker {
255*61046927SAndroid Build Coastguard Worker    assert(util_bitcount(usage_flag) == 1);
256*61046927SAndroid Build Coastguard Worker    switch (usage_flag) {
257*61046927SAndroid Build Coastguard Worker    case VK_IMAGE_USAGE_TRANSFER_SRC_BIT:
258*61046927SAndroid Build Coastguard Worker       return VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT |
259*61046927SAndroid Build Coastguard Worker              VK_FORMAT_FEATURE_BLIT_SRC_BIT;
260*61046927SAndroid Build Coastguard Worker    case VK_IMAGE_USAGE_TRANSFER_DST_BIT:
261*61046927SAndroid Build Coastguard Worker       return VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT |
262*61046927SAndroid Build Coastguard Worker              VK_FORMAT_FEATURE_BLIT_DST_BIT;
263*61046927SAndroid Build Coastguard Worker    case VK_IMAGE_USAGE_SAMPLED_BIT:
264*61046927SAndroid Build Coastguard Worker       return VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT;
265*61046927SAndroid Build Coastguard Worker    case VK_IMAGE_USAGE_STORAGE_BIT:
266*61046927SAndroid Build Coastguard Worker       return VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT;
267*61046927SAndroid Build Coastguard Worker    case VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT:
268*61046927SAndroid Build Coastguard Worker       return VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT;
269*61046927SAndroid Build Coastguard Worker    case VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT:
270*61046927SAndroid Build Coastguard Worker       return VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT;
271*61046927SAndroid Build Coastguard Worker    case VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT:
272*61046927SAndroid Build Coastguard Worker       return VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT |
273*61046927SAndroid Build Coastguard Worker              VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT;
274*61046927SAndroid Build Coastguard Worker    default:
275*61046927SAndroid Build Coastguard Worker       return 0;
276*61046927SAndroid Build Coastguard Worker    }
277*61046927SAndroid Build Coastguard Worker }
278*61046927SAndroid Build Coastguard Worker 
279*61046927SAndroid Build Coastguard Worker uint32_t
nvk_image_max_dimension(const struct nv_device_info * info,VkImageType image_type)280*61046927SAndroid Build Coastguard Worker nvk_image_max_dimension(const struct nv_device_info *info,
281*61046927SAndroid Build Coastguard Worker                         VkImageType image_type)
282*61046927SAndroid Build Coastguard Worker {
283*61046927SAndroid Build Coastguard Worker    switch (image_type) {
284*61046927SAndroid Build Coastguard Worker    case VK_IMAGE_TYPE_1D:
285*61046927SAndroid Build Coastguard Worker    case VK_IMAGE_TYPE_2D:
286*61046927SAndroid Build Coastguard Worker       return info->cls_eng3d >= PASCAL_A ? 0x8000 : 0x4000;
287*61046927SAndroid Build Coastguard Worker    case VK_IMAGE_TYPE_3D:
288*61046927SAndroid Build Coastguard Worker       return 0x4000;
289*61046927SAndroid Build Coastguard Worker    default:
290*61046927SAndroid Build Coastguard Worker       unreachable("Invalid image type");
291*61046927SAndroid Build Coastguard Worker    }
292*61046927SAndroid Build Coastguard Worker }
293*61046927SAndroid Build Coastguard Worker 
294*61046927SAndroid Build Coastguard Worker static uint64_t
get_explicit_drm_format_mod(const void * pNext)295*61046927SAndroid Build Coastguard Worker get_explicit_drm_format_mod(const void *pNext)
296*61046927SAndroid Build Coastguard Worker {
297*61046927SAndroid Build Coastguard Worker    const VkPhysicalDeviceImageDrmFormatModifierInfoEXT *drm_format_mod_info =
298*61046927SAndroid Build Coastguard Worker       vk_find_struct_const(pNext,
299*61046927SAndroid Build Coastguard Worker                            PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT);
300*61046927SAndroid Build Coastguard Worker    if (drm_format_mod_info)
301*61046927SAndroid Build Coastguard Worker       return drm_format_mod_info->drmFormatModifier;
302*61046927SAndroid Build Coastguard Worker    else
303*61046927SAndroid Build Coastguard Worker       return DRM_FORMAT_MOD_INVALID;
304*61046927SAndroid Build Coastguard Worker }
305*61046927SAndroid Build Coastguard Worker 
306*61046927SAndroid Build Coastguard Worker VKAPI_ATTR VkResult VKAPI_CALL
nvk_GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceImageFormatInfo2 * pImageFormatInfo,VkImageFormatProperties2 * pImageFormatProperties)307*61046927SAndroid Build Coastguard Worker nvk_GetPhysicalDeviceImageFormatProperties2(
308*61046927SAndroid Build Coastguard Worker    VkPhysicalDevice physicalDevice,
309*61046927SAndroid Build Coastguard Worker    const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo,
310*61046927SAndroid Build Coastguard Worker    VkImageFormatProperties2 *pImageFormatProperties)
311*61046927SAndroid Build Coastguard Worker {
312*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(nvk_physical_device, pdev, physicalDevice);
313*61046927SAndroid Build Coastguard Worker 
314*61046927SAndroid Build Coastguard Worker    const VkPhysicalDeviceExternalImageFormatInfo *external_info =
315*61046927SAndroid Build Coastguard Worker       vk_find_struct_const(pImageFormatInfo->pNext,
316*61046927SAndroid Build Coastguard Worker                            PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO);
317*61046927SAndroid Build Coastguard Worker 
318*61046927SAndroid Build Coastguard Worker    /* Initialize to zero in case we return VK_ERROR_FORMAT_NOT_SUPPORTED */
319*61046927SAndroid Build Coastguard Worker    memset(&pImageFormatProperties->imageFormatProperties, 0,
320*61046927SAndroid Build Coastguard Worker           sizeof(pImageFormatProperties->imageFormatProperties));
321*61046927SAndroid Build Coastguard Worker 
322*61046927SAndroid Build Coastguard Worker    uint64_t drm_format_mod =
323*61046927SAndroid Build Coastguard Worker       get_explicit_drm_format_mod(pImageFormatInfo->pNext);
324*61046927SAndroid Build Coastguard Worker    const struct vk_format_ycbcr_info *ycbcr_info =
325*61046927SAndroid Build Coastguard Worker       vk_format_get_ycbcr_info(pImageFormatInfo->format);
326*61046927SAndroid Build Coastguard Worker 
327*61046927SAndroid Build Coastguard Worker    /* For the purposes of these checks, we don't care about all the extra
328*61046927SAndroid Build Coastguard Worker     * YCbCr features and we just want the accumulation of features available
329*61046927SAndroid Build Coastguard Worker     * to all planes of the given format.
330*61046927SAndroid Build Coastguard Worker     */
331*61046927SAndroid Build Coastguard Worker    VkFormatFeatureFlags2 features;
332*61046927SAndroid Build Coastguard Worker    if (ycbcr_info == NULL) {
333*61046927SAndroid Build Coastguard Worker       features = nvk_get_image_plane_format_features(
334*61046927SAndroid Build Coastguard Worker          pdev, pImageFormatInfo->format, pImageFormatInfo->tiling,
335*61046927SAndroid Build Coastguard Worker          drm_format_mod);
336*61046927SAndroid Build Coastguard Worker    } else {
337*61046927SAndroid Build Coastguard Worker       features = ~0ull;
338*61046927SAndroid Build Coastguard Worker       assert(ycbcr_info->n_planes > 0);
339*61046927SAndroid Build Coastguard Worker       for (uint8_t plane = 0; plane < ycbcr_info->n_planes; plane++) {
340*61046927SAndroid Build Coastguard Worker          const VkFormat plane_format = ycbcr_info->planes[plane].format;
341*61046927SAndroid Build Coastguard Worker          features &= nvk_get_image_plane_format_features(
342*61046927SAndroid Build Coastguard Worker             pdev, plane_format, pImageFormatInfo->tiling, drm_format_mod);
343*61046927SAndroid Build Coastguard Worker       }
344*61046927SAndroid Build Coastguard Worker    }
345*61046927SAndroid Build Coastguard Worker 
346*61046927SAndroid Build Coastguard Worker    if (features == 0)
347*61046927SAndroid Build Coastguard Worker       return VK_ERROR_FORMAT_NOT_SUPPORTED;
348*61046927SAndroid Build Coastguard Worker 
349*61046927SAndroid Build Coastguard Worker    if (pImageFormatInfo->tiling == VK_IMAGE_TILING_LINEAR &&
350*61046927SAndroid Build Coastguard Worker        pImageFormatInfo->type != VK_IMAGE_TYPE_2D)
351*61046927SAndroid Build Coastguard Worker       return VK_ERROR_FORMAT_NOT_SUPPORTED;
352*61046927SAndroid Build Coastguard Worker 
353*61046927SAndroid Build Coastguard Worker    if (ycbcr_info && pImageFormatInfo->type != VK_IMAGE_TYPE_2D)
354*61046927SAndroid Build Coastguard Worker       return VK_ERROR_FORMAT_NOT_SUPPORTED;
355*61046927SAndroid Build Coastguard Worker 
356*61046927SAndroid Build Coastguard Worker    /* Maxwell B and earlier don't support sparse residency */
357*61046927SAndroid Build Coastguard Worker    if ((pImageFormatInfo->flags & VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT) &&
358*61046927SAndroid Build Coastguard Worker        pdev->info.cls_eng3d < MAXWELL_B)
359*61046927SAndroid Build Coastguard Worker       return VK_ERROR_FORMAT_NOT_SUPPORTED;
360*61046927SAndroid Build Coastguard Worker 
361*61046927SAndroid Build Coastguard Worker    /* Don't allow sparse on D32S8 cube maps.  The hardware doesn't seem to
362*61046927SAndroid Build Coastguard Worker     * handle these correctly and hard-faults instead of the expected soft
363*61046927SAndroid Build Coastguard Worker     * fault when there's sparse VA.
364*61046927SAndroid Build Coastguard Worker     */
365*61046927SAndroid Build Coastguard Worker    if (pImageFormatInfo->format == VK_FORMAT_D32_SFLOAT_S8_UINT &&
366*61046927SAndroid Build Coastguard Worker        (pImageFormatInfo->flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) &&
367*61046927SAndroid Build Coastguard Worker        (pImageFormatInfo->flags & VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT) &&
368*61046927SAndroid Build Coastguard Worker        pdev->info.cls_eng3d < TURING_A)
369*61046927SAndroid Build Coastguard Worker       return VK_ERROR_FORMAT_NOT_SUPPORTED;
370*61046927SAndroid Build Coastguard Worker 
371*61046927SAndroid Build Coastguard Worker    /* From the Vulkan 1.3.279 spec:
372*61046927SAndroid Build Coastguard Worker     *
373*61046927SAndroid Build Coastguard Worker     *    VUID-VkImageCreateInfo-tiling-04121
374*61046927SAndroid Build Coastguard Worker     *
375*61046927SAndroid Build Coastguard Worker     *    "If tiling is VK_IMAGE_TILING_LINEAR, flags must not contain
376*61046927SAndroid Build Coastguard Worker     *    VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT"
377*61046927SAndroid Build Coastguard Worker     *
378*61046927SAndroid Build Coastguard Worker     *    VUID-VkImageCreateInfo-imageType-00970
379*61046927SAndroid Build Coastguard Worker     *
380*61046927SAndroid Build Coastguard Worker     *    "If imageType is VK_IMAGE_TYPE_1D, flags must not contain
381*61046927SAndroid Build Coastguard Worker     *    VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT"
382*61046927SAndroid Build Coastguard Worker     */
383*61046927SAndroid Build Coastguard Worker    if ((pImageFormatInfo->flags & VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT) &&
384*61046927SAndroid Build Coastguard Worker        (pImageFormatInfo->type == VK_IMAGE_TYPE_1D ||
385*61046927SAndroid Build Coastguard Worker         pImageFormatInfo->tiling == VK_IMAGE_TILING_LINEAR))
386*61046927SAndroid Build Coastguard Worker       return VK_ERROR_FORMAT_NOT_SUPPORTED;
387*61046927SAndroid Build Coastguard Worker 
388*61046927SAndroid Build Coastguard Worker    /* From the Vulkan 1.3.279 spec:
389*61046927SAndroid Build Coastguard Worker     *
390*61046927SAndroid Build Coastguard Worker     *    VUID-VkImageCreateInfo-flags-09403
391*61046927SAndroid Build Coastguard Worker     *
392*61046927SAndroid Build Coastguard Worker     *    "If flags contains VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT, flags
393*61046927SAndroid Build Coastguard Worker     *    must not include VK_IMAGE_CREATE_SPARSE_ALIASED_BIT,
394*61046927SAndroid Build Coastguard Worker     *    VK_IMAGE_CREATE_SPARSE_BINDING_BIT, or
395*61046927SAndroid Build Coastguard Worker     *    VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT"
396*61046927SAndroid Build Coastguard Worker     */
397*61046927SAndroid Build Coastguard Worker    if ((pImageFormatInfo->flags & VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT) &&
398*61046927SAndroid Build Coastguard Worker        (pImageFormatInfo->flags & (VK_IMAGE_CREATE_SPARSE_ALIASED_BIT |
399*61046927SAndroid Build Coastguard Worker                                    VK_IMAGE_CREATE_SPARSE_BINDING_BIT |
400*61046927SAndroid Build Coastguard Worker                                    VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT)))
401*61046927SAndroid Build Coastguard Worker       return VK_ERROR_FORMAT_NOT_SUPPORTED;
402*61046927SAndroid Build Coastguard Worker 
403*61046927SAndroid Build Coastguard Worker    const uint32_t max_dim =
404*61046927SAndroid Build Coastguard Worker       nvk_image_max_dimension(&pdev->info, VK_IMAGE_TYPE_1D);
405*61046927SAndroid Build Coastguard Worker    VkExtent3D maxExtent;
406*61046927SAndroid Build Coastguard Worker    uint32_t maxArraySize;
407*61046927SAndroid Build Coastguard Worker    switch (pImageFormatInfo->type) {
408*61046927SAndroid Build Coastguard Worker    case VK_IMAGE_TYPE_1D:
409*61046927SAndroid Build Coastguard Worker       maxExtent = (VkExtent3D) { max_dim, 1, 1 };
410*61046927SAndroid Build Coastguard Worker       maxArraySize = 2048;
411*61046927SAndroid Build Coastguard Worker       break;
412*61046927SAndroid Build Coastguard Worker    case VK_IMAGE_TYPE_2D:
413*61046927SAndroid Build Coastguard Worker       maxExtent = (VkExtent3D) { max_dim, max_dim, 1 };
414*61046927SAndroid Build Coastguard Worker       maxArraySize = 2048;
415*61046927SAndroid Build Coastguard Worker       break;
416*61046927SAndroid Build Coastguard Worker    case VK_IMAGE_TYPE_3D:
417*61046927SAndroid Build Coastguard Worker       maxExtent = (VkExtent3D) { max_dim, max_dim, max_dim };
418*61046927SAndroid Build Coastguard Worker       maxArraySize = 1;
419*61046927SAndroid Build Coastguard Worker       break;
420*61046927SAndroid Build Coastguard Worker    default:
421*61046927SAndroid Build Coastguard Worker       unreachable("Invalid image type");
422*61046927SAndroid Build Coastguard Worker    }
423*61046927SAndroid Build Coastguard Worker    if (pImageFormatInfo->tiling == VK_IMAGE_TILING_LINEAR)
424*61046927SAndroid Build Coastguard Worker       maxArraySize = 1;
425*61046927SAndroid Build Coastguard Worker 
426*61046927SAndroid Build Coastguard Worker    assert(util_is_power_of_two_nonzero(max_dim));
427*61046927SAndroid Build Coastguard Worker    uint32_t maxMipLevels = util_logbase2(max_dim) + 1;
428*61046927SAndroid Build Coastguard Worker    if (ycbcr_info != NULL || pImageFormatInfo->tiling == VK_IMAGE_TILING_LINEAR)
429*61046927SAndroid Build Coastguard Worker        maxMipLevels = 1;
430*61046927SAndroid Build Coastguard Worker 
431*61046927SAndroid Build Coastguard Worker    VkSampleCountFlags sampleCounts = VK_SAMPLE_COUNT_1_BIT;
432*61046927SAndroid Build Coastguard Worker    if (pImageFormatInfo->tiling == VK_IMAGE_TILING_OPTIMAL &&
433*61046927SAndroid Build Coastguard Worker        pImageFormatInfo->type == VK_IMAGE_TYPE_2D &&
434*61046927SAndroid Build Coastguard Worker        ycbcr_info == NULL &&
435*61046927SAndroid Build Coastguard Worker        (features & (VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT |
436*61046927SAndroid Build Coastguard Worker                     VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT)) &&
437*61046927SAndroid Build Coastguard Worker        !(pImageFormatInfo->flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT)) {
438*61046927SAndroid Build Coastguard Worker       sampleCounts = VK_SAMPLE_COUNT_1_BIT |
439*61046927SAndroid Build Coastguard Worker                      VK_SAMPLE_COUNT_2_BIT |
440*61046927SAndroid Build Coastguard Worker                      VK_SAMPLE_COUNT_4_BIT |
441*61046927SAndroid Build Coastguard Worker                      VK_SAMPLE_COUNT_8_BIT;
442*61046927SAndroid Build Coastguard Worker    }
443*61046927SAndroid Build Coastguard Worker 
444*61046927SAndroid Build Coastguard Worker    /* From the Vulkan 1.2.199 spec:
445*61046927SAndroid Build Coastguard Worker     *
446*61046927SAndroid Build Coastguard Worker     *    "VK_IMAGE_CREATE_EXTENDED_USAGE_BIT specifies that the image can be
447*61046927SAndroid Build Coastguard Worker     *    created with usage flags that are not supported for the format the
448*61046927SAndroid Build Coastguard Worker     *    image is created with but are supported for at least one format a
449*61046927SAndroid Build Coastguard Worker     *    VkImageView created from the image can have."
450*61046927SAndroid Build Coastguard Worker     *
451*61046927SAndroid Build Coastguard Worker     * If VK_IMAGE_CREATE_EXTENDED_USAGE_BIT is set, views can be created with
452*61046927SAndroid Build Coastguard Worker     * different usage than the image so we can't always filter on usage.
453*61046927SAndroid Build Coastguard Worker     * There is one exception to this below for storage.
454*61046927SAndroid Build Coastguard Worker     */
455*61046927SAndroid Build Coastguard Worker    const VkImageUsageFlags image_usage = pImageFormatInfo->usage;
456*61046927SAndroid Build Coastguard Worker    VkImageUsageFlags view_usage = image_usage;
457*61046927SAndroid Build Coastguard Worker    if (pImageFormatInfo->flags & VK_IMAGE_CREATE_EXTENDED_USAGE_BIT)
458*61046927SAndroid Build Coastguard Worker       view_usage = 0;
459*61046927SAndroid Build Coastguard Worker 
460*61046927SAndroid Build Coastguard Worker    u_foreach_bit(b, view_usage) {
461*61046927SAndroid Build Coastguard Worker       VkFormatFeatureFlags2 usage_features =
462*61046927SAndroid Build Coastguard Worker          vk_image_usage_to_format_features(1 << b);
463*61046927SAndroid Build Coastguard Worker       if (usage_features && !(features & usage_features))
464*61046927SAndroid Build Coastguard Worker          return VK_ERROR_FORMAT_NOT_SUPPORTED;
465*61046927SAndroid Build Coastguard Worker    }
466*61046927SAndroid Build Coastguard Worker 
467*61046927SAndroid Build Coastguard Worker    const VkExternalMemoryProperties *ext_mem_props = NULL;
468*61046927SAndroid Build Coastguard Worker    if (external_info != NULL && external_info->handleType != 0) {
469*61046927SAndroid Build Coastguard Worker       bool tiling_has_explicit_layout;
470*61046927SAndroid Build Coastguard Worker       switch (pImageFormatInfo->tiling) {
471*61046927SAndroid Build Coastguard Worker       case VK_IMAGE_TILING_LINEAR:
472*61046927SAndroid Build Coastguard Worker       case VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT:
473*61046927SAndroid Build Coastguard Worker          tiling_has_explicit_layout = true;
474*61046927SAndroid Build Coastguard Worker          break;
475*61046927SAndroid Build Coastguard Worker       case VK_IMAGE_TILING_OPTIMAL:
476*61046927SAndroid Build Coastguard Worker          tiling_has_explicit_layout = false;
477*61046927SAndroid Build Coastguard Worker          break;
478*61046927SAndroid Build Coastguard Worker       default:
479*61046927SAndroid Build Coastguard Worker          unreachable("Unsupported VkImageTiling");
480*61046927SAndroid Build Coastguard Worker       }
481*61046927SAndroid Build Coastguard Worker 
482*61046927SAndroid Build Coastguard Worker       switch (external_info->handleType) {
483*61046927SAndroid Build Coastguard Worker       case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
484*61046927SAndroid Build Coastguard Worker          /* No special restrictions */
485*61046927SAndroid Build Coastguard Worker          if (tiling_has_explicit_layout) {
486*61046927SAndroid Build Coastguard Worker             /* With an explicit memory layout, we don't care which type of
487*61046927SAndroid Build Coastguard Worker              * fd the image belongs too. Both OPAQUE_FD and DMA_BUF are
488*61046927SAndroid Build Coastguard Worker              * interchangeable here.
489*61046927SAndroid Build Coastguard Worker              */
490*61046927SAndroid Build Coastguard Worker             ext_mem_props = &nvk_dma_buf_mem_props;
491*61046927SAndroid Build Coastguard Worker          } else {
492*61046927SAndroid Build Coastguard Worker             ext_mem_props = &nvk_opaque_fd_mem_props;
493*61046927SAndroid Build Coastguard Worker          }
494*61046927SAndroid Build Coastguard Worker          break;
495*61046927SAndroid Build Coastguard Worker 
496*61046927SAndroid Build Coastguard Worker       case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
497*61046927SAndroid Build Coastguard Worker          if (!tiling_has_explicit_layout) {
498*61046927SAndroid Build Coastguard Worker             return vk_errorf(pdev, VK_ERROR_FORMAT_NOT_SUPPORTED,
499*61046927SAndroid Build Coastguard Worker                              "VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT "
500*61046927SAndroid Build Coastguard Worker                              "requires VK_IMAGE_TILING_LINEAR or "
501*61046927SAndroid Build Coastguard Worker                              "VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT");
502*61046927SAndroid Build Coastguard Worker          }
503*61046927SAndroid Build Coastguard Worker          ext_mem_props = &nvk_dma_buf_mem_props;
504*61046927SAndroid Build Coastguard Worker          break;
505*61046927SAndroid Build Coastguard Worker 
506*61046927SAndroid Build Coastguard Worker       default:
507*61046927SAndroid Build Coastguard Worker          /* From the Vulkan 1.3.256 spec:
508*61046927SAndroid Build Coastguard Worker           *
509*61046927SAndroid Build Coastguard Worker           *    "If handleType is not compatible with the [parameters] in
510*61046927SAndroid Build Coastguard Worker           *    VkPhysicalDeviceImageFormatInfo2, then
511*61046927SAndroid Build Coastguard Worker           *    vkGetPhysicalDeviceImageFormatProperties2 returns
512*61046927SAndroid Build Coastguard Worker           *    VK_ERROR_FORMAT_NOT_SUPPORTED."
513*61046927SAndroid Build Coastguard Worker           */
514*61046927SAndroid Build Coastguard Worker          return vk_errorf(pdev, VK_ERROR_FORMAT_NOT_SUPPORTED,
515*61046927SAndroid Build Coastguard Worker                           "unsupported VkExternalMemoryHandleTypeFlagBits: %s ",
516*61046927SAndroid Build Coastguard Worker                            vk_ExternalMemoryHandleTypeFlagBits_to_str(external_info->handleType));
517*61046927SAndroid Build Coastguard Worker       }
518*61046927SAndroid Build Coastguard Worker    }
519*61046927SAndroid Build Coastguard Worker 
520*61046927SAndroid Build Coastguard Worker    const unsigned plane_count =
521*61046927SAndroid Build Coastguard Worker       vk_format_get_plane_count(pImageFormatInfo->format);
522*61046927SAndroid Build Coastguard Worker 
523*61046927SAndroid Build Coastguard Worker    /* From the Vulkan 1.3.259 spec, VkImageCreateInfo:
524*61046927SAndroid Build Coastguard Worker     *
525*61046927SAndroid Build Coastguard Worker     *    VUID-VkImageCreateInfo-imageCreateFormatFeatures-02260
526*61046927SAndroid Build Coastguard Worker     *
527*61046927SAndroid Build Coastguard Worker     *    "If format is a multi-planar format, and if imageCreateFormatFeatures
528*61046927SAndroid Build Coastguard Worker     *    (as defined in Image Creation Limits) does not contain
529*61046927SAndroid Build Coastguard Worker     *    VK_FORMAT_FEATURE_DISJOINT_BIT, then flags must not contain
530*61046927SAndroid Build Coastguard Worker     *    VK_IMAGE_CREATE_DISJOINT_BIT"
531*61046927SAndroid Build Coastguard Worker     *
532*61046927SAndroid Build Coastguard Worker     * This is satisfied trivially because we support DISJOINT on all
533*61046927SAndroid Build Coastguard Worker     * multi-plane formats.  Also,
534*61046927SAndroid Build Coastguard Worker     *
535*61046927SAndroid Build Coastguard Worker     *    VUID-VkImageCreateInfo-format-01577
536*61046927SAndroid Build Coastguard Worker     *
537*61046927SAndroid Build Coastguard Worker     *    "If format is not a multi-planar format, and flags does not include
538*61046927SAndroid Build Coastguard Worker     *    VK_IMAGE_CREATE_ALIAS_BIT, flags must not contain
539*61046927SAndroid Build Coastguard Worker     *    VK_IMAGE_CREATE_DISJOINT_BIT"
540*61046927SAndroid Build Coastguard Worker     */
541*61046927SAndroid Build Coastguard Worker    if (plane_count == 1 &&
542*61046927SAndroid Build Coastguard Worker        !(pImageFormatInfo->flags & VK_IMAGE_CREATE_ALIAS_BIT) &&
543*61046927SAndroid Build Coastguard Worker        (pImageFormatInfo->flags & VK_IMAGE_CREATE_DISJOINT_BIT))
544*61046927SAndroid Build Coastguard Worker       return VK_ERROR_FORMAT_NOT_SUPPORTED;
545*61046927SAndroid Build Coastguard Worker 
546*61046927SAndroid Build Coastguard Worker    if (ycbcr_info &&
547*61046927SAndroid Build Coastguard Worker        ((pImageFormatInfo->flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT) ||
548*61046927SAndroid Build Coastguard Worker        (pImageFormatInfo->flags & VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT)))
549*61046927SAndroid Build Coastguard Worker       return VK_ERROR_FORMAT_NOT_SUPPORTED;
550*61046927SAndroid Build Coastguard Worker 
551*61046927SAndroid Build Coastguard Worker    pImageFormatProperties->imageFormatProperties = (VkImageFormatProperties) {
552*61046927SAndroid Build Coastguard Worker       .maxExtent = maxExtent,
553*61046927SAndroid Build Coastguard Worker       .maxMipLevels = maxMipLevels,
554*61046927SAndroid Build Coastguard Worker       .maxArrayLayers = maxArraySize,
555*61046927SAndroid Build Coastguard Worker       .sampleCounts = sampleCounts,
556*61046927SAndroid Build Coastguard Worker       .maxResourceSize = UINT32_MAX, /* TODO */
557*61046927SAndroid Build Coastguard Worker    };
558*61046927SAndroid Build Coastguard Worker 
559*61046927SAndroid Build Coastguard Worker    vk_foreach_struct(s, pImageFormatProperties->pNext) {
560*61046927SAndroid Build Coastguard Worker       switch (s->sType) {
561*61046927SAndroid Build Coastguard Worker       case VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES: {
562*61046927SAndroid Build Coastguard Worker          VkExternalImageFormatProperties *p = (void *)s;
563*61046927SAndroid Build Coastguard Worker          /* From the Vulkan 1.3.256 spec:
564*61046927SAndroid Build Coastguard Worker           *
565*61046927SAndroid Build Coastguard Worker           *    "If handleType is 0, vkGetPhysicalDeviceImageFormatProperties2
566*61046927SAndroid Build Coastguard Worker           *    will behave as if VkPhysicalDeviceExternalImageFormatInfo was
567*61046927SAndroid Build Coastguard Worker           *    not present, and VkExternalImageFormatProperties will be
568*61046927SAndroid Build Coastguard Worker           *    ignored."
569*61046927SAndroid Build Coastguard Worker           *
570*61046927SAndroid Build Coastguard Worker           * This is true if and only if ext_mem_props == NULL
571*61046927SAndroid Build Coastguard Worker           */
572*61046927SAndroid Build Coastguard Worker          if (ext_mem_props != NULL)
573*61046927SAndroid Build Coastguard Worker             p->externalMemoryProperties = *ext_mem_props;
574*61046927SAndroid Build Coastguard Worker          break;
575*61046927SAndroid Build Coastguard Worker       }
576*61046927SAndroid Build Coastguard Worker       case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES: {
577*61046927SAndroid Build Coastguard Worker          VkSamplerYcbcrConversionImageFormatProperties *ycbcr_props = (void *) s;
578*61046927SAndroid Build Coastguard Worker          ycbcr_props->combinedImageSamplerDescriptorCount = plane_count;
579*61046927SAndroid Build Coastguard Worker          break;
580*61046927SAndroid Build Coastguard Worker       }
581*61046927SAndroid Build Coastguard Worker       default:
582*61046927SAndroid Build Coastguard Worker          vk_debug_ignored_stype(s->sType);
583*61046927SAndroid Build Coastguard Worker          break;
584*61046927SAndroid Build Coastguard Worker       }
585*61046927SAndroid Build Coastguard Worker    }
586*61046927SAndroid Build Coastguard Worker 
587*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
588*61046927SAndroid Build Coastguard Worker }
589*61046927SAndroid Build Coastguard Worker 
590*61046927SAndroid Build Coastguard Worker static enum nil_image_dim
vk_image_type_to_nil_dim(VkImageType type)591*61046927SAndroid Build Coastguard Worker vk_image_type_to_nil_dim(VkImageType type)
592*61046927SAndroid Build Coastguard Worker {
593*61046927SAndroid Build Coastguard Worker    switch (type) {
594*61046927SAndroid Build Coastguard Worker    case VK_IMAGE_TYPE_1D:  return NIL_IMAGE_DIM_1D;
595*61046927SAndroid Build Coastguard Worker    case VK_IMAGE_TYPE_2D:  return NIL_IMAGE_DIM_2D;
596*61046927SAndroid Build Coastguard Worker    case VK_IMAGE_TYPE_3D:  return NIL_IMAGE_DIM_3D;
597*61046927SAndroid Build Coastguard Worker    default:
598*61046927SAndroid Build Coastguard Worker       unreachable("Invalid image type");
599*61046927SAndroid Build Coastguard Worker    }
600*61046927SAndroid Build Coastguard Worker }
601*61046927SAndroid Build Coastguard Worker 
602*61046927SAndroid Build Coastguard Worker static VkSparseImageFormatProperties
nvk_fill_sparse_image_fmt_props(VkImageAspectFlags aspects,const enum pipe_format format,const enum nil_image_dim dim,const enum nil_sample_layout sample_layout)603*61046927SAndroid Build Coastguard Worker nvk_fill_sparse_image_fmt_props(VkImageAspectFlags aspects,
604*61046927SAndroid Build Coastguard Worker                                 const enum pipe_format format,
605*61046927SAndroid Build Coastguard Worker                                 const enum nil_image_dim dim,
606*61046927SAndroid Build Coastguard Worker                                 const enum nil_sample_layout sample_layout)
607*61046927SAndroid Build Coastguard Worker {
608*61046927SAndroid Build Coastguard Worker    struct nil_Extent4D_Pixels sparse_block_extent_px =
609*61046927SAndroid Build Coastguard Worker       nil_sparse_block_extent_px(nil_format(format), dim, sample_layout);
610*61046927SAndroid Build Coastguard Worker 
611*61046927SAndroid Build Coastguard Worker    assert(sparse_block_extent_px.array_len == 1);
612*61046927SAndroid Build Coastguard Worker 
613*61046927SAndroid Build Coastguard Worker    VkSparseImageFormatProperties sparse_format_props = {
614*61046927SAndroid Build Coastguard Worker       .aspectMask = aspects,
615*61046927SAndroid Build Coastguard Worker       .flags = VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT,
616*61046927SAndroid Build Coastguard Worker       .imageGranularity = {
617*61046927SAndroid Build Coastguard Worker          .width = sparse_block_extent_px.width,
618*61046927SAndroid Build Coastguard Worker          .height = sparse_block_extent_px.height,
619*61046927SAndroid Build Coastguard Worker          .depth = sparse_block_extent_px.depth,
620*61046927SAndroid Build Coastguard Worker       },
621*61046927SAndroid Build Coastguard Worker    };
622*61046927SAndroid Build Coastguard Worker 
623*61046927SAndroid Build Coastguard Worker    return sparse_format_props;
624*61046927SAndroid Build Coastguard Worker }
625*61046927SAndroid Build Coastguard Worker 
626*61046927SAndroid Build Coastguard Worker VKAPI_ATTR void VKAPI_CALL
nvk_GetPhysicalDeviceSparseImageFormatProperties2(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceSparseImageFormatInfo2 * pFormatInfo,uint32_t * pPropertyCount,VkSparseImageFormatProperties2 * pProperties)627*61046927SAndroid Build Coastguard Worker nvk_GetPhysicalDeviceSparseImageFormatProperties2(
628*61046927SAndroid Build Coastguard Worker     VkPhysicalDevice physicalDevice,
629*61046927SAndroid Build Coastguard Worker     const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo,
630*61046927SAndroid Build Coastguard Worker     uint32_t *pPropertyCount,
631*61046927SAndroid Build Coastguard Worker     VkSparseImageFormatProperties2 *pProperties)
632*61046927SAndroid Build Coastguard Worker {
633*61046927SAndroid Build Coastguard Worker    VkResult result;
634*61046927SAndroid Build Coastguard Worker 
635*61046927SAndroid Build Coastguard Worker    /* Check if the given format info is valid first before returning sparse
636*61046927SAndroid Build Coastguard Worker     * props.  The easiest way to do this is to just call
637*61046927SAndroid Build Coastguard Worker     * nvk_GetPhysicalDeviceImageFormatProperties2()
638*61046927SAndroid Build Coastguard Worker     */
639*61046927SAndroid Build Coastguard Worker    const VkPhysicalDeviceImageFormatInfo2 img_fmt_info = {
640*61046927SAndroid Build Coastguard Worker       .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
641*61046927SAndroid Build Coastguard Worker       .format = pFormatInfo->format,
642*61046927SAndroid Build Coastguard Worker       .type = pFormatInfo->type,
643*61046927SAndroid Build Coastguard Worker       .tiling = pFormatInfo->tiling,
644*61046927SAndroid Build Coastguard Worker       .usage = pFormatInfo->usage,
645*61046927SAndroid Build Coastguard Worker       .flags = VK_IMAGE_CREATE_SPARSE_BINDING_BIT |
646*61046927SAndroid Build Coastguard Worker                VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT,
647*61046927SAndroid Build Coastguard Worker    };
648*61046927SAndroid Build Coastguard Worker 
649*61046927SAndroid Build Coastguard Worker    VkImageFormatProperties2 img_fmt_props2 = {
650*61046927SAndroid Build Coastguard Worker       .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
651*61046927SAndroid Build Coastguard Worker       .pNext = NULL,
652*61046927SAndroid Build Coastguard Worker    };
653*61046927SAndroid Build Coastguard Worker 
654*61046927SAndroid Build Coastguard Worker    result = nvk_GetPhysicalDeviceImageFormatProperties2(physicalDevice,
655*61046927SAndroid Build Coastguard Worker                                                         &img_fmt_info,
656*61046927SAndroid Build Coastguard Worker                                                         &img_fmt_props2);
657*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS) {
658*61046927SAndroid Build Coastguard Worker       *pPropertyCount = 0;
659*61046927SAndroid Build Coastguard Worker       return;
660*61046927SAndroid Build Coastguard Worker    }
661*61046927SAndroid Build Coastguard Worker 
662*61046927SAndroid Build Coastguard Worker    const VkImageFormatProperties *props = &img_fmt_props2.imageFormatProperties;
663*61046927SAndroid Build Coastguard Worker    if (!(pFormatInfo->samples & props->sampleCounts)) {
664*61046927SAndroid Build Coastguard Worker       *pPropertyCount = 0;
665*61046927SAndroid Build Coastguard Worker       return;
666*61046927SAndroid Build Coastguard Worker    }
667*61046927SAndroid Build Coastguard Worker 
668*61046927SAndroid Build Coastguard Worker    VK_OUTARRAY_MAKE_TYPED(VkSparseImageFormatProperties2, out,
669*61046927SAndroid Build Coastguard Worker                           pProperties, pPropertyCount);
670*61046927SAndroid Build Coastguard Worker 
671*61046927SAndroid Build Coastguard Worker    VkImageAspectFlags aspects = vk_format_aspects(pFormatInfo->format);
672*61046927SAndroid Build Coastguard Worker    const enum pipe_format pipe_format =
673*61046927SAndroid Build Coastguard Worker       vk_format_to_pipe_format(pFormatInfo->format);
674*61046927SAndroid Build Coastguard Worker    const enum nil_image_dim dim = vk_image_type_to_nil_dim(pFormatInfo->type);
675*61046927SAndroid Build Coastguard Worker    const enum nil_sample_layout sample_layout =
676*61046927SAndroid Build Coastguard Worker       nil_choose_sample_layout(pFormatInfo->samples);
677*61046927SAndroid Build Coastguard Worker 
678*61046927SAndroid Build Coastguard Worker    vk_outarray_append_typed(VkSparseImageFormatProperties2, &out, props) {
679*61046927SAndroid Build Coastguard Worker       props->properties = nvk_fill_sparse_image_fmt_props(aspects, pipe_format,
680*61046927SAndroid Build Coastguard Worker                                                           dim, sample_layout);
681*61046927SAndroid Build Coastguard Worker    }
682*61046927SAndroid Build Coastguard Worker }
683*61046927SAndroid Build Coastguard Worker 
684*61046927SAndroid Build Coastguard Worker static VkResult
nvk_image_init(struct nvk_device * dev,struct nvk_image * image,const VkImageCreateInfo * pCreateInfo)685*61046927SAndroid Build Coastguard Worker nvk_image_init(struct nvk_device *dev,
686*61046927SAndroid Build Coastguard Worker                struct nvk_image *image,
687*61046927SAndroid Build Coastguard Worker                const VkImageCreateInfo *pCreateInfo)
688*61046927SAndroid Build Coastguard Worker {
689*61046927SAndroid Build Coastguard Worker    struct nvk_physical_device *pdev = nvk_device_physical(dev);
690*61046927SAndroid Build Coastguard Worker 
691*61046927SAndroid Build Coastguard Worker    vk_image_init(&dev->vk, &image->vk, pCreateInfo);
692*61046927SAndroid Build Coastguard Worker 
693*61046927SAndroid Build Coastguard Worker    if ((image->vk.usage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
694*61046927SAndroid Build Coastguard Worker                            VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) &&
695*61046927SAndroid Build Coastguard Worker        image->vk.samples > 1) {
696*61046927SAndroid Build Coastguard Worker       image->vk.usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
697*61046927SAndroid Build Coastguard Worker       image->vk.stencil_usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
698*61046927SAndroid Build Coastguard Worker    }
699*61046927SAndroid Build Coastguard Worker 
700*61046927SAndroid Build Coastguard Worker    if (image->vk.usage & VK_IMAGE_USAGE_TRANSFER_SRC_BIT)
701*61046927SAndroid Build Coastguard Worker       image->vk.usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
702*61046927SAndroid Build Coastguard Worker    if (image->vk.usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT)
703*61046927SAndroid Build Coastguard Worker       image->vk.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
704*61046927SAndroid Build Coastguard Worker 
705*61046927SAndroid Build Coastguard Worker    nil_image_usage_flags usage = 0;
706*61046927SAndroid Build Coastguard Worker    if (pCreateInfo->tiling == VK_IMAGE_TILING_LINEAR)
707*61046927SAndroid Build Coastguard Worker       usage |= NIL_IMAGE_USAGE_LINEAR_BIT;
708*61046927SAndroid Build Coastguard Worker    if (pCreateInfo->flags & VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT)
709*61046927SAndroid Build Coastguard Worker       usage |= NIL_IMAGE_USAGE_2D_VIEW_BIT;
710*61046927SAndroid Build Coastguard Worker    if (pCreateInfo->flags & VK_IMAGE_CREATE_2D_VIEW_COMPATIBLE_BIT_EXT)
711*61046927SAndroid Build Coastguard Worker       usage |= NIL_IMAGE_USAGE_2D_VIEW_BIT;
712*61046927SAndroid Build Coastguard Worker 
713*61046927SAndroid Build Coastguard Worker    /* In order to be able to clear 3D depth/stencil images, we need to bind
714*61046927SAndroid Build Coastguard Worker     * them as 2D arrays.  Fortunately, 3D depth/stencil shouldn't be common.
715*61046927SAndroid Build Coastguard Worker     */
716*61046927SAndroid Build Coastguard Worker    if ((image->vk.aspects & (VK_IMAGE_ASPECT_DEPTH_BIT |
717*61046927SAndroid Build Coastguard Worker                              VK_IMAGE_ASPECT_STENCIL_BIT)) &&
718*61046927SAndroid Build Coastguard Worker        pCreateInfo->imageType == VK_IMAGE_TYPE_3D)
719*61046927SAndroid Build Coastguard Worker       usage |= NIL_IMAGE_USAGE_2D_VIEW_BIT;
720*61046927SAndroid Build Coastguard Worker 
721*61046927SAndroid Build Coastguard Worker    image->plane_count = vk_format_get_plane_count(pCreateInfo->format);
722*61046927SAndroid Build Coastguard Worker    image->disjoint = image->plane_count > 1 &&
723*61046927SAndroid Build Coastguard Worker                      (pCreateInfo->flags & VK_IMAGE_CREATE_DISJOINT_BIT);
724*61046927SAndroid Build Coastguard Worker 
725*61046927SAndroid Build Coastguard Worker    if (image->vk.create_flags & VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT) {
726*61046927SAndroid Build Coastguard Worker       /* Sparse multiplane is not supported */
727*61046927SAndroid Build Coastguard Worker       assert(image->plane_count == 1);
728*61046927SAndroid Build Coastguard Worker       usage |= NIL_IMAGE_USAGE_SPARSE_RESIDENCY_BIT;
729*61046927SAndroid Build Coastguard Worker    }
730*61046927SAndroid Build Coastguard Worker 
731*61046927SAndroid Build Coastguard Worker    uint32_t explicit_row_stride_B = 0;
732*61046927SAndroid Build Coastguard Worker    if (image->vk.tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) {
733*61046927SAndroid Build Coastguard Worker       /* Modifiers are not supported with YCbCr */
734*61046927SAndroid Build Coastguard Worker       assert(image->plane_count == 1);
735*61046927SAndroid Build Coastguard Worker 
736*61046927SAndroid Build Coastguard Worker       const struct VkImageDrmFormatModifierExplicitCreateInfoEXT *mod_explicit_info =
737*61046927SAndroid Build Coastguard Worker          vk_find_struct_const(pCreateInfo->pNext,
738*61046927SAndroid Build Coastguard Worker                               IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT);
739*61046927SAndroid Build Coastguard Worker       if (mod_explicit_info) {
740*61046927SAndroid Build Coastguard Worker          image->vk.drm_format_mod = mod_explicit_info->drmFormatModifier;
741*61046927SAndroid Build Coastguard Worker          /* Normally with explicit modifiers, the client specifies all strides,
742*61046927SAndroid Build Coastguard Worker           * however in our case, we can only really make use of this in the linear
743*61046927SAndroid Build Coastguard Worker           * case, and we can only create 2D non-array linear images, so ultimately
744*61046927SAndroid Build Coastguard Worker           * we only care about the row stride.
745*61046927SAndroid Build Coastguard Worker           */
746*61046927SAndroid Build Coastguard Worker          explicit_row_stride_B = mod_explicit_info->pPlaneLayouts->rowPitch;
747*61046927SAndroid Build Coastguard Worker       } else {
748*61046927SAndroid Build Coastguard Worker          const struct VkImageDrmFormatModifierListCreateInfoEXT *mod_list_info =
749*61046927SAndroid Build Coastguard Worker             vk_find_struct_const(pCreateInfo->pNext,
750*61046927SAndroid Build Coastguard Worker                                  IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT);
751*61046927SAndroid Build Coastguard Worker 
752*61046927SAndroid Build Coastguard Worker          enum pipe_format p_format =
753*61046927SAndroid Build Coastguard Worker             vk_format_to_pipe_format(pCreateInfo->format);
754*61046927SAndroid Build Coastguard Worker          image->vk.drm_format_mod =
755*61046927SAndroid Build Coastguard Worker             nil_select_best_drm_format_mod(&pdev->info, nil_format(p_format),
756*61046927SAndroid Build Coastguard Worker                                            mod_list_info->drmFormatModifierCount,
757*61046927SAndroid Build Coastguard Worker                                            mod_list_info->pDrmFormatModifiers);
758*61046927SAndroid Build Coastguard Worker          assert(image->vk.drm_format_mod != DRM_FORMAT_MOD_INVALID);
759*61046927SAndroid Build Coastguard Worker       }
760*61046927SAndroid Build Coastguard Worker 
761*61046927SAndroid Build Coastguard Worker       if (image->vk.drm_format_mod == DRM_FORMAT_MOD_LINEAR) {
762*61046927SAndroid Build Coastguard Worker          /* We only have one shadow plane per nvk_image */
763*61046927SAndroid Build Coastguard Worker          assert(image->plane_count == 1);
764*61046927SAndroid Build Coastguard Worker 
765*61046927SAndroid Build Coastguard Worker          struct nil_image_init_info tiled_shadow_nil_info = {
766*61046927SAndroid Build Coastguard Worker             .dim = vk_image_type_to_nil_dim(pCreateInfo->imageType),
767*61046927SAndroid Build Coastguard Worker             .format = nil_format(vk_format_to_pipe_format(image->vk.format)),
768*61046927SAndroid Build Coastguard Worker             .modifier = DRM_FORMAT_MOD_INVALID,
769*61046927SAndroid Build Coastguard Worker             .extent_px = {
770*61046927SAndroid Build Coastguard Worker                .width = pCreateInfo->extent.width,
771*61046927SAndroid Build Coastguard Worker                .height = pCreateInfo->extent.height,
772*61046927SAndroid Build Coastguard Worker                .depth = pCreateInfo->extent.depth,
773*61046927SAndroid Build Coastguard Worker                .array_len = pCreateInfo->arrayLayers,
774*61046927SAndroid Build Coastguard Worker             },
775*61046927SAndroid Build Coastguard Worker             .levels = pCreateInfo->mipLevels,
776*61046927SAndroid Build Coastguard Worker             .samples = pCreateInfo->samples,
777*61046927SAndroid Build Coastguard Worker             .usage = usage & ~NIL_IMAGE_USAGE_LINEAR_BIT,
778*61046927SAndroid Build Coastguard Worker             .explicit_row_stride_B = 0,
779*61046927SAndroid Build Coastguard Worker          };
780*61046927SAndroid Build Coastguard Worker          image->linear_tiled_shadow.nil =
781*61046927SAndroid Build Coastguard Worker             nil_image_new(&pdev->info, &tiled_shadow_nil_info);
782*61046927SAndroid Build Coastguard Worker       }
783*61046927SAndroid Build Coastguard Worker    }
784*61046927SAndroid Build Coastguard Worker 
785*61046927SAndroid Build Coastguard Worker    const struct vk_format_ycbcr_info *ycbcr_info =
786*61046927SAndroid Build Coastguard Worker       vk_format_get_ycbcr_info(pCreateInfo->format);
787*61046927SAndroid Build Coastguard Worker    for (uint8_t plane = 0; plane < image->plane_count; plane++) {
788*61046927SAndroid Build Coastguard Worker       VkFormat format = ycbcr_info ?
789*61046927SAndroid Build Coastguard Worker          ycbcr_info->planes[plane].format : pCreateInfo->format;
790*61046927SAndroid Build Coastguard Worker       const uint8_t width_scale = ycbcr_info ?
791*61046927SAndroid Build Coastguard Worker          ycbcr_info->planes[plane].denominator_scales[0] : 1;
792*61046927SAndroid Build Coastguard Worker       const uint8_t height_scale = ycbcr_info ?
793*61046927SAndroid Build Coastguard Worker          ycbcr_info->planes[plane].denominator_scales[1] : 1;
794*61046927SAndroid Build Coastguard Worker       struct nil_image_init_info nil_info = {
795*61046927SAndroid Build Coastguard Worker          .dim = vk_image_type_to_nil_dim(pCreateInfo->imageType),
796*61046927SAndroid Build Coastguard Worker          .format = nil_format(vk_format_to_pipe_format(format)),
797*61046927SAndroid Build Coastguard Worker          .modifier = image->vk.drm_format_mod,
798*61046927SAndroid Build Coastguard Worker          .extent_px = {
799*61046927SAndroid Build Coastguard Worker             .width = pCreateInfo->extent.width / width_scale,
800*61046927SAndroid Build Coastguard Worker             .height = pCreateInfo->extent.height / height_scale,
801*61046927SAndroid Build Coastguard Worker             .depth = pCreateInfo->extent.depth,
802*61046927SAndroid Build Coastguard Worker             .array_len = pCreateInfo->arrayLayers,
803*61046927SAndroid Build Coastguard Worker          },
804*61046927SAndroid Build Coastguard Worker          .levels = pCreateInfo->mipLevels,
805*61046927SAndroid Build Coastguard Worker          .samples = pCreateInfo->samples,
806*61046927SAndroid Build Coastguard Worker          .usage = usage,
807*61046927SAndroid Build Coastguard Worker          .explicit_row_stride_B = explicit_row_stride_B,
808*61046927SAndroid Build Coastguard Worker       };
809*61046927SAndroid Build Coastguard Worker 
810*61046927SAndroid Build Coastguard Worker       image->planes[plane].nil = nil_image_new(&pdev->info, &nil_info);
811*61046927SAndroid Build Coastguard Worker    }
812*61046927SAndroid Build Coastguard Worker 
813*61046927SAndroid Build Coastguard Worker    if (image->vk.format == VK_FORMAT_D32_SFLOAT_S8_UINT) {
814*61046927SAndroid Build Coastguard Worker       struct nil_image_init_info stencil_nil_info = {
815*61046927SAndroid Build Coastguard Worker          .dim = vk_image_type_to_nil_dim(pCreateInfo->imageType),
816*61046927SAndroid Build Coastguard Worker          .format = nil_format(PIPE_FORMAT_R32_UINT),
817*61046927SAndroid Build Coastguard Worker          .modifier = DRM_FORMAT_MOD_INVALID,
818*61046927SAndroid Build Coastguard Worker          .extent_px = {
819*61046927SAndroid Build Coastguard Worker             .width = pCreateInfo->extent.width,
820*61046927SAndroid Build Coastguard Worker             .height = pCreateInfo->extent.height,
821*61046927SAndroid Build Coastguard Worker             .depth = pCreateInfo->extent.depth,
822*61046927SAndroid Build Coastguard Worker             .array_len = pCreateInfo->arrayLayers,
823*61046927SAndroid Build Coastguard Worker          },
824*61046927SAndroid Build Coastguard Worker          .levels = pCreateInfo->mipLevels,
825*61046927SAndroid Build Coastguard Worker          .samples = pCreateInfo->samples,
826*61046927SAndroid Build Coastguard Worker          .usage = usage,
827*61046927SAndroid Build Coastguard Worker          .explicit_row_stride_B = 0,
828*61046927SAndroid Build Coastguard Worker       };
829*61046927SAndroid Build Coastguard Worker 
830*61046927SAndroid Build Coastguard Worker       image->stencil_copy_temp.nil =
831*61046927SAndroid Build Coastguard Worker          nil_image_new(&pdev->info, &stencil_nil_info);
832*61046927SAndroid Build Coastguard Worker    }
833*61046927SAndroid Build Coastguard Worker 
834*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
835*61046927SAndroid Build Coastguard Worker }
836*61046927SAndroid Build Coastguard Worker 
837*61046927SAndroid Build Coastguard Worker static void
nvk_image_plane_size_align_B(struct nvk_device * dev,const struct nvk_image * image,const struct nvk_image_plane * plane,uint64_t * size_B_out,uint64_t * align_B_out)838*61046927SAndroid Build Coastguard Worker nvk_image_plane_size_align_B(struct nvk_device *dev,
839*61046927SAndroid Build Coastguard Worker                              const struct nvk_image *image,
840*61046927SAndroid Build Coastguard Worker                              const struct nvk_image_plane *plane,
841*61046927SAndroid Build Coastguard Worker                              uint64_t *size_B_out, uint64_t *align_B_out)
842*61046927SAndroid Build Coastguard Worker {
843*61046927SAndroid Build Coastguard Worker    struct nvk_physical_device *pdev = nvk_device_physical(dev);
844*61046927SAndroid Build Coastguard Worker    const bool sparse_bound =
845*61046927SAndroid Build Coastguard Worker       image->vk.create_flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT;
846*61046927SAndroid Build Coastguard Worker 
847*61046927SAndroid Build Coastguard Worker    assert(util_is_power_of_two_or_zero64(plane->nil.align_B));
848*61046927SAndroid Build Coastguard Worker    if (sparse_bound || plane->nil.pte_kind) {
849*61046927SAndroid Build Coastguard Worker       *align_B_out = MAX2(plane->nil.align_B, pdev->nvkmd->bind_align_B);
850*61046927SAndroid Build Coastguard Worker    } else {
851*61046927SAndroid Build Coastguard Worker       *align_B_out = plane->nil.align_B;
852*61046927SAndroid Build Coastguard Worker    }
853*61046927SAndroid Build Coastguard Worker    *size_B_out = align64(plane->nil.size_B, *align_B_out);
854*61046927SAndroid Build Coastguard Worker }
855*61046927SAndroid Build Coastguard Worker 
856*61046927SAndroid Build Coastguard Worker static VkResult
nvk_image_plane_alloc_va(struct nvk_device * dev,const struct nvk_image * image,struct nvk_image_plane * plane)857*61046927SAndroid Build Coastguard Worker nvk_image_plane_alloc_va(struct nvk_device *dev,
858*61046927SAndroid Build Coastguard Worker                          const struct nvk_image *image,
859*61046927SAndroid Build Coastguard Worker                          struct nvk_image_plane *plane)
860*61046927SAndroid Build Coastguard Worker {
861*61046927SAndroid Build Coastguard Worker    VkResult result;
862*61046927SAndroid Build Coastguard Worker 
863*61046927SAndroid Build Coastguard Worker    const bool sparse_bound =
864*61046927SAndroid Build Coastguard Worker       image->vk.create_flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT;
865*61046927SAndroid Build Coastguard Worker    const bool sparse_resident =
866*61046927SAndroid Build Coastguard Worker       image->vk.create_flags & VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT;
867*61046927SAndroid Build Coastguard Worker    assert(sparse_bound || !sparse_resident);
868*61046927SAndroid Build Coastguard Worker 
869*61046927SAndroid Build Coastguard Worker    if (sparse_bound || plane->nil.pte_kind) {
870*61046927SAndroid Build Coastguard Worker       enum nvkmd_va_flags va_flags = 0;
871*61046927SAndroid Build Coastguard Worker       if (sparse_resident)
872*61046927SAndroid Build Coastguard Worker          va_flags |= NVKMD_VA_SPARSE;
873*61046927SAndroid Build Coastguard Worker 
874*61046927SAndroid Build Coastguard Worker       uint64_t va_size_B, va_align_B;
875*61046927SAndroid Build Coastguard Worker       nvk_image_plane_size_align_B(dev, image, plane, &va_size_B, &va_align_B);
876*61046927SAndroid Build Coastguard Worker 
877*61046927SAndroid Build Coastguard Worker       result = nvkmd_dev_alloc_va(dev->nvkmd, &dev->vk.base,
878*61046927SAndroid Build Coastguard Worker                                   va_flags, plane->nil.pte_kind,
879*61046927SAndroid Build Coastguard Worker                                   va_size_B, va_align_B,
880*61046927SAndroid Build Coastguard Worker                                   0 /* fixed_addr */, &plane->va);
881*61046927SAndroid Build Coastguard Worker       if (result != VK_SUCCESS)
882*61046927SAndroid Build Coastguard Worker          return result;
883*61046927SAndroid Build Coastguard Worker 
884*61046927SAndroid Build Coastguard Worker       plane->addr = plane->va->addr;
885*61046927SAndroid Build Coastguard Worker    }
886*61046927SAndroid Build Coastguard Worker 
887*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
888*61046927SAndroid Build Coastguard Worker }
889*61046927SAndroid Build Coastguard Worker 
890*61046927SAndroid Build Coastguard Worker static void
nvk_image_plane_finish(struct nvk_device * dev,struct nvk_image_plane * plane,VkImageCreateFlags create_flags,const VkAllocationCallbacks * pAllocator)891*61046927SAndroid Build Coastguard Worker nvk_image_plane_finish(struct nvk_device *dev,
892*61046927SAndroid Build Coastguard Worker                        struct nvk_image_plane *plane,
893*61046927SAndroid Build Coastguard Worker                        VkImageCreateFlags create_flags,
894*61046927SAndroid Build Coastguard Worker                        const VkAllocationCallbacks *pAllocator)
895*61046927SAndroid Build Coastguard Worker {
896*61046927SAndroid Build Coastguard Worker    if (plane->va != NULL)
897*61046927SAndroid Build Coastguard Worker       nvkmd_va_free(plane->va);
898*61046927SAndroid Build Coastguard Worker }
899*61046927SAndroid Build Coastguard Worker 
900*61046927SAndroid Build Coastguard Worker static void
nvk_image_finish(struct nvk_device * dev,struct nvk_image * image,const VkAllocationCallbacks * pAllocator)901*61046927SAndroid Build Coastguard Worker nvk_image_finish(struct nvk_device *dev, struct nvk_image *image,
902*61046927SAndroid Build Coastguard Worker                  const VkAllocationCallbacks *pAllocator)
903*61046927SAndroid Build Coastguard Worker {
904*61046927SAndroid Build Coastguard Worker    for (uint8_t plane = 0; plane < image->plane_count; plane++) {
905*61046927SAndroid Build Coastguard Worker       nvk_image_plane_finish(dev, &image->planes[plane],
906*61046927SAndroid Build Coastguard Worker                              image->vk.create_flags, pAllocator);
907*61046927SAndroid Build Coastguard Worker    }
908*61046927SAndroid Build Coastguard Worker 
909*61046927SAndroid Build Coastguard Worker    if (image->stencil_copy_temp.nil.size_B > 0) {
910*61046927SAndroid Build Coastguard Worker       nvk_image_plane_finish(dev, &image->stencil_copy_temp,
911*61046927SAndroid Build Coastguard Worker                              image->vk.create_flags, pAllocator);
912*61046927SAndroid Build Coastguard Worker    }
913*61046927SAndroid Build Coastguard Worker 
914*61046927SAndroid Build Coastguard Worker    assert(image->linear_tiled_shadow.va == NULL);
915*61046927SAndroid Build Coastguard Worker    if (image->linear_tiled_shadow_mem != NULL)
916*61046927SAndroid Build Coastguard Worker       nvkmd_mem_unref(image->linear_tiled_shadow_mem);
917*61046927SAndroid Build Coastguard Worker 
918*61046927SAndroid Build Coastguard Worker    vk_image_finish(&image->vk);
919*61046927SAndroid Build Coastguard Worker }
920*61046927SAndroid Build Coastguard Worker 
921*61046927SAndroid Build Coastguard Worker VKAPI_ATTR VkResult VKAPI_CALL
nvk_CreateImage(VkDevice _device,const VkImageCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkImage * pImage)922*61046927SAndroid Build Coastguard Worker nvk_CreateImage(VkDevice _device,
923*61046927SAndroid Build Coastguard Worker                 const VkImageCreateInfo *pCreateInfo,
924*61046927SAndroid Build Coastguard Worker                 const VkAllocationCallbacks *pAllocator,
925*61046927SAndroid Build Coastguard Worker                 VkImage *pImage)
926*61046927SAndroid Build Coastguard Worker {
927*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(nvk_device, dev, _device);
928*61046927SAndroid Build Coastguard Worker    struct nvk_physical_device *pdev = nvk_device_physical(dev);
929*61046927SAndroid Build Coastguard Worker    struct nvk_image *image;
930*61046927SAndroid Build Coastguard Worker    VkResult result;
931*61046927SAndroid Build Coastguard Worker 
932*61046927SAndroid Build Coastguard Worker #ifdef NVK_USE_WSI_PLATFORM
933*61046927SAndroid Build Coastguard Worker    /* Ignore swapchain creation info on Android. Since we don't have an
934*61046927SAndroid Build Coastguard Worker     * implementation in Mesa, we're guaranteed to access an Android object
935*61046927SAndroid Build Coastguard Worker     * incorrectly.
936*61046927SAndroid Build Coastguard Worker     */
937*61046927SAndroid Build Coastguard Worker    const VkImageSwapchainCreateInfoKHR *swapchain_info =
938*61046927SAndroid Build Coastguard Worker       vk_find_struct_const(pCreateInfo->pNext, IMAGE_SWAPCHAIN_CREATE_INFO_KHR);
939*61046927SAndroid Build Coastguard Worker    if (swapchain_info && swapchain_info->swapchain != VK_NULL_HANDLE) {
940*61046927SAndroid Build Coastguard Worker       return wsi_common_create_swapchain_image(&pdev->wsi_device,
941*61046927SAndroid Build Coastguard Worker                                                pCreateInfo,
942*61046927SAndroid Build Coastguard Worker                                                swapchain_info->swapchain,
943*61046927SAndroid Build Coastguard Worker                                                pImage);
944*61046927SAndroid Build Coastguard Worker    }
945*61046927SAndroid Build Coastguard Worker #endif
946*61046927SAndroid Build Coastguard Worker 
947*61046927SAndroid Build Coastguard Worker    image = vk_zalloc2(&dev->vk.alloc, pAllocator, sizeof(*image), 8,
948*61046927SAndroid Build Coastguard Worker                       VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
949*61046927SAndroid Build Coastguard Worker    if (!image)
950*61046927SAndroid Build Coastguard Worker       return vk_error(dev, VK_ERROR_OUT_OF_HOST_MEMORY);
951*61046927SAndroid Build Coastguard Worker 
952*61046927SAndroid Build Coastguard Worker    result = nvk_image_init(dev, image, pCreateInfo);
953*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS) {
954*61046927SAndroid Build Coastguard Worker       vk_free2(&dev->vk.alloc, pAllocator, image);
955*61046927SAndroid Build Coastguard Worker       return result;
956*61046927SAndroid Build Coastguard Worker    }
957*61046927SAndroid Build Coastguard Worker 
958*61046927SAndroid Build Coastguard Worker    for (uint8_t plane = 0; plane < image->plane_count; plane++) {
959*61046927SAndroid Build Coastguard Worker       result = nvk_image_plane_alloc_va(dev, image, &image->planes[plane]);
960*61046927SAndroid Build Coastguard Worker       if (result != VK_SUCCESS) {
961*61046927SAndroid Build Coastguard Worker          nvk_image_finish(dev, image, pAllocator);
962*61046927SAndroid Build Coastguard Worker          vk_free2(&dev->vk.alloc, pAllocator, image);
963*61046927SAndroid Build Coastguard Worker          return result;
964*61046927SAndroid Build Coastguard Worker       }
965*61046927SAndroid Build Coastguard Worker    }
966*61046927SAndroid Build Coastguard Worker 
967*61046927SAndroid Build Coastguard Worker    if (image->stencil_copy_temp.nil.size_B > 0) {
968*61046927SAndroid Build Coastguard Worker       result = nvk_image_plane_alloc_va(dev, image, &image->stencil_copy_temp);
969*61046927SAndroid Build Coastguard Worker       if (result != VK_SUCCESS) {
970*61046927SAndroid Build Coastguard Worker          nvk_image_finish(dev, image, pAllocator);
971*61046927SAndroid Build Coastguard Worker          vk_free2(&dev->vk.alloc, pAllocator, image);
972*61046927SAndroid Build Coastguard Worker          return result;
973*61046927SAndroid Build Coastguard Worker       }
974*61046927SAndroid Build Coastguard Worker    }
975*61046927SAndroid Build Coastguard Worker 
976*61046927SAndroid Build Coastguard Worker    if (image->linear_tiled_shadow.nil.size_B > 0) {
977*61046927SAndroid Build Coastguard Worker       struct nvk_image_plane *shadow = &image->linear_tiled_shadow;
978*61046927SAndroid Build Coastguard Worker       result = nvkmd_dev_alloc_tiled_mem(dev->nvkmd, &dev->vk.base,
979*61046927SAndroid Build Coastguard Worker                                          shadow->nil.size_B, shadow->nil.align_B,
980*61046927SAndroid Build Coastguard Worker                                          shadow->nil.pte_kind, shadow->nil.tile_mode,
981*61046927SAndroid Build Coastguard Worker                                          NVKMD_MEM_LOCAL,
982*61046927SAndroid Build Coastguard Worker                                          &image->linear_tiled_shadow_mem);
983*61046927SAndroid Build Coastguard Worker       if (result != VK_SUCCESS) {
984*61046927SAndroid Build Coastguard Worker          nvk_image_finish(dev, image, pAllocator);
985*61046927SAndroid Build Coastguard Worker          vk_free2(&dev->vk.alloc, pAllocator, image);
986*61046927SAndroid Build Coastguard Worker          return result;
987*61046927SAndroid Build Coastguard Worker       }
988*61046927SAndroid Build Coastguard Worker       shadow->addr = image->linear_tiled_shadow_mem->va->addr;
989*61046927SAndroid Build Coastguard Worker    }
990*61046927SAndroid Build Coastguard Worker 
991*61046927SAndroid Build Coastguard Worker    *pImage = nvk_image_to_handle(image);
992*61046927SAndroid Build Coastguard Worker 
993*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
994*61046927SAndroid Build Coastguard Worker }
995*61046927SAndroid Build Coastguard Worker 
996*61046927SAndroid Build Coastguard Worker VKAPI_ATTR void VKAPI_CALL
nvk_DestroyImage(VkDevice device,VkImage _image,const VkAllocationCallbacks * pAllocator)997*61046927SAndroid Build Coastguard Worker nvk_DestroyImage(VkDevice device,
998*61046927SAndroid Build Coastguard Worker                  VkImage _image,
999*61046927SAndroid Build Coastguard Worker                  const VkAllocationCallbacks *pAllocator)
1000*61046927SAndroid Build Coastguard Worker {
1001*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(nvk_device, dev, device);
1002*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(nvk_image, image, _image);
1003*61046927SAndroid Build Coastguard Worker 
1004*61046927SAndroid Build Coastguard Worker    if (!image)
1005*61046927SAndroid Build Coastguard Worker       return;
1006*61046927SAndroid Build Coastguard Worker 
1007*61046927SAndroid Build Coastguard Worker    nvk_image_finish(dev, image, pAllocator);
1008*61046927SAndroid Build Coastguard Worker    vk_free2(&dev->vk.alloc, pAllocator, image);
1009*61046927SAndroid Build Coastguard Worker }
1010*61046927SAndroid Build Coastguard Worker 
1011*61046927SAndroid Build Coastguard Worker static void
nvk_image_plane_add_req(struct nvk_device * dev,const struct nvk_image * image,const struct nvk_image_plane * plane,uint64_t * size_B,uint32_t * align_B)1012*61046927SAndroid Build Coastguard Worker nvk_image_plane_add_req(struct nvk_device *dev,
1013*61046927SAndroid Build Coastguard Worker                         const struct nvk_image *image,
1014*61046927SAndroid Build Coastguard Worker                         const struct nvk_image_plane *plane,
1015*61046927SAndroid Build Coastguard Worker                         uint64_t *size_B, uint32_t *align_B)
1016*61046927SAndroid Build Coastguard Worker {
1017*61046927SAndroid Build Coastguard Worker    assert(util_is_power_of_two_or_zero64(*align_B));
1018*61046927SAndroid Build Coastguard Worker    uint64_t plane_size_B, plane_align_B;
1019*61046927SAndroid Build Coastguard Worker    nvk_image_plane_size_align_B(dev, image, plane,
1020*61046927SAndroid Build Coastguard Worker                                 &plane_size_B, &plane_align_B);
1021*61046927SAndroid Build Coastguard Worker 
1022*61046927SAndroid Build Coastguard Worker    *align_B = MAX2(*align_B, plane_align_B);
1023*61046927SAndroid Build Coastguard Worker    *size_B = align64(*size_B, plane_align_B);
1024*61046927SAndroid Build Coastguard Worker    *size_B += plane_size_B;
1025*61046927SAndroid Build Coastguard Worker }
1026*61046927SAndroid Build Coastguard Worker 
1027*61046927SAndroid Build Coastguard Worker static void
nvk_get_image_memory_requirements(struct nvk_device * dev,struct nvk_image * image,VkImageAspectFlags aspects,VkMemoryRequirements2 * pMemoryRequirements)1028*61046927SAndroid Build Coastguard Worker nvk_get_image_memory_requirements(struct nvk_device *dev,
1029*61046927SAndroid Build Coastguard Worker                                   struct nvk_image *image,
1030*61046927SAndroid Build Coastguard Worker                                   VkImageAspectFlags aspects,
1031*61046927SAndroid Build Coastguard Worker                                   VkMemoryRequirements2 *pMemoryRequirements)
1032*61046927SAndroid Build Coastguard Worker {
1033*61046927SAndroid Build Coastguard Worker    struct nvk_physical_device *pdev = nvk_device_physical(dev);
1034*61046927SAndroid Build Coastguard Worker    uint32_t memory_types = (1 << pdev->mem_type_count) - 1;
1035*61046927SAndroid Build Coastguard Worker 
1036*61046927SAndroid Build Coastguard Worker    // TODO hope for the best?
1037*61046927SAndroid Build Coastguard Worker 
1038*61046927SAndroid Build Coastguard Worker    uint64_t size_B = 0;
1039*61046927SAndroid Build Coastguard Worker    uint32_t align_B = 0;
1040*61046927SAndroid Build Coastguard Worker    if (image->disjoint) {
1041*61046927SAndroid Build Coastguard Worker       uint8_t plane = nvk_image_memory_aspects_to_plane(image, aspects);
1042*61046927SAndroid Build Coastguard Worker       nvk_image_plane_add_req(dev, image, &image->planes[plane],
1043*61046927SAndroid Build Coastguard Worker                               &size_B, &align_B);
1044*61046927SAndroid Build Coastguard Worker    } else {
1045*61046927SAndroid Build Coastguard Worker       for (unsigned plane = 0; plane < image->plane_count; plane++) {
1046*61046927SAndroid Build Coastguard Worker          nvk_image_plane_add_req(dev, image, &image->planes[plane],
1047*61046927SAndroid Build Coastguard Worker                                  &size_B, &align_B);
1048*61046927SAndroid Build Coastguard Worker       }
1049*61046927SAndroid Build Coastguard Worker    }
1050*61046927SAndroid Build Coastguard Worker 
1051*61046927SAndroid Build Coastguard Worker    if (image->stencil_copy_temp.nil.size_B > 0) {
1052*61046927SAndroid Build Coastguard Worker       nvk_image_plane_add_req(dev, image, &image->stencil_copy_temp,
1053*61046927SAndroid Build Coastguard Worker                               &size_B, &align_B);
1054*61046927SAndroid Build Coastguard Worker    }
1055*61046927SAndroid Build Coastguard Worker 
1056*61046927SAndroid Build Coastguard Worker    pMemoryRequirements->memoryRequirements.memoryTypeBits = memory_types;
1057*61046927SAndroid Build Coastguard Worker    pMemoryRequirements->memoryRequirements.alignment = align_B;
1058*61046927SAndroid Build Coastguard Worker    pMemoryRequirements->memoryRequirements.size = size_B;
1059*61046927SAndroid Build Coastguard Worker 
1060*61046927SAndroid Build Coastguard Worker    vk_foreach_struct_const(ext, pMemoryRequirements->pNext) {
1061*61046927SAndroid Build Coastguard Worker       switch (ext->sType) {
1062*61046927SAndroid Build Coastguard Worker       case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: {
1063*61046927SAndroid Build Coastguard Worker          VkMemoryDedicatedRequirements *dedicated = (void *)ext;
1064*61046927SAndroid Build Coastguard Worker          dedicated->prefersDedicatedAllocation =
1065*61046927SAndroid Build Coastguard Worker             image->vk.tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT;
1066*61046927SAndroid Build Coastguard Worker          dedicated->requiresDedicatedAllocation =
1067*61046927SAndroid Build Coastguard Worker             image->vk.tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT;
1068*61046927SAndroid Build Coastguard Worker          break;
1069*61046927SAndroid Build Coastguard Worker       }
1070*61046927SAndroid Build Coastguard Worker       default:
1071*61046927SAndroid Build Coastguard Worker          vk_debug_ignored_stype(ext->sType);
1072*61046927SAndroid Build Coastguard Worker          break;
1073*61046927SAndroid Build Coastguard Worker       }
1074*61046927SAndroid Build Coastguard Worker    }
1075*61046927SAndroid Build Coastguard Worker }
1076*61046927SAndroid Build Coastguard Worker 
1077*61046927SAndroid Build Coastguard Worker VKAPI_ATTR void VKAPI_CALL
nvk_GetImageMemoryRequirements2(VkDevice device,const VkImageMemoryRequirementsInfo2 * pInfo,VkMemoryRequirements2 * pMemoryRequirements)1078*61046927SAndroid Build Coastguard Worker nvk_GetImageMemoryRequirements2(VkDevice device,
1079*61046927SAndroid Build Coastguard Worker                                 const VkImageMemoryRequirementsInfo2 *pInfo,
1080*61046927SAndroid Build Coastguard Worker                                 VkMemoryRequirements2 *pMemoryRequirements)
1081*61046927SAndroid Build Coastguard Worker {
1082*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(nvk_device, dev, device);
1083*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(nvk_image, image, pInfo->image);
1084*61046927SAndroid Build Coastguard Worker 
1085*61046927SAndroid Build Coastguard Worker    const VkImagePlaneMemoryRequirementsInfo *plane_info =
1086*61046927SAndroid Build Coastguard Worker       vk_find_struct_const(pInfo->pNext, IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO);
1087*61046927SAndroid Build Coastguard Worker    const VkImageAspectFlags aspects =
1088*61046927SAndroid Build Coastguard Worker       image->disjoint ? plane_info->planeAspect : image->vk.aspects;
1089*61046927SAndroid Build Coastguard Worker 
1090*61046927SAndroid Build Coastguard Worker    nvk_get_image_memory_requirements(dev, image, aspects,
1091*61046927SAndroid Build Coastguard Worker                                      pMemoryRequirements);
1092*61046927SAndroid Build Coastguard Worker }
1093*61046927SAndroid Build Coastguard Worker 
1094*61046927SAndroid Build Coastguard Worker VKAPI_ATTR void VKAPI_CALL
nvk_GetDeviceImageMemoryRequirements(VkDevice device,const VkDeviceImageMemoryRequirements * pInfo,VkMemoryRequirements2 * pMemoryRequirements)1095*61046927SAndroid Build Coastguard Worker nvk_GetDeviceImageMemoryRequirements(VkDevice device,
1096*61046927SAndroid Build Coastguard Worker                                      const VkDeviceImageMemoryRequirements *pInfo,
1097*61046927SAndroid Build Coastguard Worker                                      VkMemoryRequirements2 *pMemoryRequirements)
1098*61046927SAndroid Build Coastguard Worker {
1099*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(nvk_device, dev, device);
1100*61046927SAndroid Build Coastguard Worker    ASSERTED VkResult result;
1101*61046927SAndroid Build Coastguard Worker    struct nvk_image image = {0};
1102*61046927SAndroid Build Coastguard Worker 
1103*61046927SAndroid Build Coastguard Worker    result = nvk_image_init(dev, &image, pInfo->pCreateInfo);
1104*61046927SAndroid Build Coastguard Worker    assert(result == VK_SUCCESS);
1105*61046927SAndroid Build Coastguard Worker 
1106*61046927SAndroid Build Coastguard Worker    const VkImageAspectFlags aspects =
1107*61046927SAndroid Build Coastguard Worker       image.disjoint ? pInfo->planeAspect : image.vk.aspects;
1108*61046927SAndroid Build Coastguard Worker 
1109*61046927SAndroid Build Coastguard Worker    nvk_get_image_memory_requirements(dev, &image, aspects,
1110*61046927SAndroid Build Coastguard Worker                                      pMemoryRequirements);
1111*61046927SAndroid Build Coastguard Worker 
1112*61046927SAndroid Build Coastguard Worker    nvk_image_finish(dev, &image, NULL);
1113*61046927SAndroid Build Coastguard Worker }
1114*61046927SAndroid Build Coastguard Worker 
1115*61046927SAndroid Build Coastguard Worker static VkSparseImageMemoryRequirements
nvk_fill_sparse_image_memory_reqs(const struct nil_image * nil,const struct nil_image * stencil_tmp,VkImageAspectFlags aspects)1116*61046927SAndroid Build Coastguard Worker nvk_fill_sparse_image_memory_reqs(const struct nil_image *nil,
1117*61046927SAndroid Build Coastguard Worker                                   const struct nil_image *stencil_tmp,
1118*61046927SAndroid Build Coastguard Worker                                   VkImageAspectFlags aspects)
1119*61046927SAndroid Build Coastguard Worker {
1120*61046927SAndroid Build Coastguard Worker    VkSparseImageFormatProperties sparse_format_props =
1121*61046927SAndroid Build Coastguard Worker       nvk_fill_sparse_image_fmt_props(aspects, nil->format.p_format,
1122*61046927SAndroid Build Coastguard Worker                                       nil->dim, nil->sample_layout);
1123*61046927SAndroid Build Coastguard Worker 
1124*61046927SAndroid Build Coastguard Worker    assert(nil->mip_tail_first_lod <= nil->num_levels);
1125*61046927SAndroid Build Coastguard Worker    VkSparseImageMemoryRequirements sparse_memory_reqs = {
1126*61046927SAndroid Build Coastguard Worker       .formatProperties = sparse_format_props,
1127*61046927SAndroid Build Coastguard Worker       .imageMipTailFirstLod = nil->mip_tail_first_lod,
1128*61046927SAndroid Build Coastguard Worker       .imageMipTailStride = 0,
1129*61046927SAndroid Build Coastguard Worker    };
1130*61046927SAndroid Build Coastguard Worker 
1131*61046927SAndroid Build Coastguard Worker    if (nil->mip_tail_first_lod == 0) {
1132*61046927SAndroid Build Coastguard Worker       sparse_memory_reqs.imageMipTailSize = nil->size_B;
1133*61046927SAndroid Build Coastguard Worker       sparse_memory_reqs.imageMipTailOffset = 0;
1134*61046927SAndroid Build Coastguard Worker    } else if (nil->mip_tail_first_lod < nil->num_levels) {
1135*61046927SAndroid Build Coastguard Worker       sparse_memory_reqs.imageMipTailSize =
1136*61046927SAndroid Build Coastguard Worker          nil_image_mip_tail_size_B(nil) * nil->extent_px.array_len;
1137*61046927SAndroid Build Coastguard Worker       sparse_memory_reqs.imageMipTailOffset = NVK_MIP_TAIL_START_OFFSET;
1138*61046927SAndroid Build Coastguard Worker    } else {
1139*61046927SAndroid Build Coastguard Worker       sparse_memory_reqs.imageMipTailSize = 0;
1140*61046927SAndroid Build Coastguard Worker       sparse_memory_reqs.imageMipTailOffset = NVK_MIP_TAIL_START_OFFSET;
1141*61046927SAndroid Build Coastguard Worker    }
1142*61046927SAndroid Build Coastguard Worker 
1143*61046927SAndroid Build Coastguard Worker    if (stencil_tmp != NULL)
1144*61046927SAndroid Build Coastguard Worker       sparse_memory_reqs.imageMipTailSize += stencil_tmp->size_B;
1145*61046927SAndroid Build Coastguard Worker 
1146*61046927SAndroid Build Coastguard Worker    return sparse_memory_reqs;
1147*61046927SAndroid Build Coastguard Worker }
1148*61046927SAndroid Build Coastguard Worker 
1149*61046927SAndroid Build Coastguard Worker static void
nvk_get_image_sparse_memory_requirements(struct nvk_device * dev,struct nvk_image * image,VkImageAspectFlags aspects,uint32_t * pSparseMemoryRequirementCount,VkSparseImageMemoryRequirements2 * pSparseMemoryRequirements)1150*61046927SAndroid Build Coastguard Worker nvk_get_image_sparse_memory_requirements(
1151*61046927SAndroid Build Coastguard Worker    struct nvk_device *dev,
1152*61046927SAndroid Build Coastguard Worker    struct nvk_image *image,
1153*61046927SAndroid Build Coastguard Worker    VkImageAspectFlags aspects,
1154*61046927SAndroid Build Coastguard Worker    uint32_t *pSparseMemoryRequirementCount,
1155*61046927SAndroid Build Coastguard Worker    VkSparseImageMemoryRequirements2 *pSparseMemoryRequirements)
1156*61046927SAndroid Build Coastguard Worker {
1157*61046927SAndroid Build Coastguard Worker    VK_OUTARRAY_MAKE_TYPED(VkSparseImageMemoryRequirements2, out,
1158*61046927SAndroid Build Coastguard Worker                           pSparseMemoryRequirements,
1159*61046927SAndroid Build Coastguard Worker                           pSparseMemoryRequirementCount);
1160*61046927SAndroid Build Coastguard Worker 
1161*61046927SAndroid Build Coastguard Worker    /* From the Vulkan 1.3.279 spec:
1162*61046927SAndroid Build Coastguard Worker     *
1163*61046927SAndroid Build Coastguard Worker     *    "The sparse image must have been created using the
1164*61046927SAndroid Build Coastguard Worker     *    VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT flag to retrieve valid sparse
1165*61046927SAndroid Build Coastguard Worker     *    image memory requirements."
1166*61046927SAndroid Build Coastguard Worker     */
1167*61046927SAndroid Build Coastguard Worker    if (!(image->vk.create_flags & VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT))
1168*61046927SAndroid Build Coastguard Worker       return;
1169*61046927SAndroid Build Coastguard Worker 
1170*61046927SAndroid Build Coastguard Worker    /* We don't support multiplane sparse for now */
1171*61046927SAndroid Build Coastguard Worker    if (image->plane_count > 1)
1172*61046927SAndroid Build Coastguard Worker       return;
1173*61046927SAndroid Build Coastguard Worker 
1174*61046927SAndroid Build Coastguard Worker    const struct nil_image *stencil_tmp = NULL;
1175*61046927SAndroid Build Coastguard Worker    if (image->stencil_copy_temp.nil.size_B > 0)
1176*61046927SAndroid Build Coastguard Worker       stencil_tmp = &image->stencil_copy_temp.nil;
1177*61046927SAndroid Build Coastguard Worker 
1178*61046927SAndroid Build Coastguard Worker    vk_outarray_append_typed(VkSparseImageMemoryRequirements2, &out, reqs) {
1179*61046927SAndroid Build Coastguard Worker       reqs->memoryRequirements =
1180*61046927SAndroid Build Coastguard Worker          nvk_fill_sparse_image_memory_reqs(&image->planes[0].nil,
1181*61046927SAndroid Build Coastguard Worker                                            stencil_tmp, aspects);
1182*61046927SAndroid Build Coastguard Worker    };
1183*61046927SAndroid Build Coastguard Worker }
1184*61046927SAndroid Build Coastguard Worker 
1185*61046927SAndroid Build Coastguard Worker VKAPI_ATTR void VKAPI_CALL
nvk_GetImageSparseMemoryRequirements2(VkDevice device,const VkImageSparseMemoryRequirementsInfo2 * pInfo,uint32_t * pSparseMemoryRequirementCount,VkSparseImageMemoryRequirements2 * pSparseMemoryRequirements)1186*61046927SAndroid Build Coastguard Worker nvk_GetImageSparseMemoryRequirements2(
1187*61046927SAndroid Build Coastguard Worker    VkDevice device,
1188*61046927SAndroid Build Coastguard Worker    const VkImageSparseMemoryRequirementsInfo2* pInfo,
1189*61046927SAndroid Build Coastguard Worker    uint32_t* pSparseMemoryRequirementCount,
1190*61046927SAndroid Build Coastguard Worker    VkSparseImageMemoryRequirements2* pSparseMemoryRequirements)
1191*61046927SAndroid Build Coastguard Worker {
1192*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(nvk_device, dev, device);
1193*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(nvk_image, image, pInfo->image);
1194*61046927SAndroid Build Coastguard Worker 
1195*61046927SAndroid Build Coastguard Worker    const VkImageAspectFlags aspects = image->vk.aspects;
1196*61046927SAndroid Build Coastguard Worker 
1197*61046927SAndroid Build Coastguard Worker    nvk_get_image_sparse_memory_requirements(dev, image, aspects,
1198*61046927SAndroid Build Coastguard Worker                                             pSparseMemoryRequirementCount,
1199*61046927SAndroid Build Coastguard Worker                                             pSparseMemoryRequirements);
1200*61046927SAndroid Build Coastguard Worker }
1201*61046927SAndroid Build Coastguard Worker 
1202*61046927SAndroid Build Coastguard Worker VKAPI_ATTR void VKAPI_CALL
nvk_GetDeviceImageSparseMemoryRequirements(VkDevice device,const VkDeviceImageMemoryRequirements * pInfo,uint32_t * pSparseMemoryRequirementCount,VkSparseImageMemoryRequirements2 * pSparseMemoryRequirements)1203*61046927SAndroid Build Coastguard Worker nvk_GetDeviceImageSparseMemoryRequirements(
1204*61046927SAndroid Build Coastguard Worker    VkDevice device,
1205*61046927SAndroid Build Coastguard Worker    const VkDeviceImageMemoryRequirements* pInfo,
1206*61046927SAndroid Build Coastguard Worker    uint32_t *pSparseMemoryRequirementCount,
1207*61046927SAndroid Build Coastguard Worker    VkSparseImageMemoryRequirements2 *pSparseMemoryRequirements)
1208*61046927SAndroid Build Coastguard Worker {
1209*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(nvk_device, dev, device);
1210*61046927SAndroid Build Coastguard Worker    ASSERTED VkResult result;
1211*61046927SAndroid Build Coastguard Worker    struct nvk_image image = {0};
1212*61046927SAndroid Build Coastguard Worker 
1213*61046927SAndroid Build Coastguard Worker    result = nvk_image_init(dev, &image, pInfo->pCreateInfo);
1214*61046927SAndroid Build Coastguard Worker    assert(result == VK_SUCCESS);
1215*61046927SAndroid Build Coastguard Worker 
1216*61046927SAndroid Build Coastguard Worker    const VkImageAspectFlags aspects =
1217*61046927SAndroid Build Coastguard Worker       image.disjoint ? pInfo->planeAspect : image.vk.aspects;
1218*61046927SAndroid Build Coastguard Worker 
1219*61046927SAndroid Build Coastguard Worker    nvk_get_image_sparse_memory_requirements(dev, &image, aspects,
1220*61046927SAndroid Build Coastguard Worker                                             pSparseMemoryRequirementCount,
1221*61046927SAndroid Build Coastguard Worker                                             pSparseMemoryRequirements);
1222*61046927SAndroid Build Coastguard Worker 
1223*61046927SAndroid Build Coastguard Worker    nvk_image_finish(dev, &image, NULL);
1224*61046927SAndroid Build Coastguard Worker }
1225*61046927SAndroid Build Coastguard Worker 
1226*61046927SAndroid Build Coastguard Worker static void
nvk_get_image_subresource_layout(struct nvk_device * dev,struct nvk_image * image,const VkImageSubresource2KHR * pSubresource,VkSubresourceLayout2KHR * pLayout)1227*61046927SAndroid Build Coastguard Worker nvk_get_image_subresource_layout(struct nvk_device *dev,
1228*61046927SAndroid Build Coastguard Worker                                  struct nvk_image *image,
1229*61046927SAndroid Build Coastguard Worker                                  const VkImageSubresource2KHR *pSubresource,
1230*61046927SAndroid Build Coastguard Worker                                  VkSubresourceLayout2KHR *pLayout)
1231*61046927SAndroid Build Coastguard Worker {
1232*61046927SAndroid Build Coastguard Worker    const VkImageSubresource *isr = &pSubresource->imageSubresource;
1233*61046927SAndroid Build Coastguard Worker 
1234*61046927SAndroid Build Coastguard Worker    const uint8_t p = nvk_image_memory_aspects_to_plane(image, isr->aspectMask);
1235*61046927SAndroid Build Coastguard Worker    const struct nvk_image_plane *plane = &image->planes[p];
1236*61046927SAndroid Build Coastguard Worker 
1237*61046927SAndroid Build Coastguard Worker    uint64_t offset_B = 0;
1238*61046927SAndroid Build Coastguard Worker    if (!image->disjoint) {
1239*61046927SAndroid Build Coastguard Worker       uint32_t align_B = 0;
1240*61046927SAndroid Build Coastguard Worker       for (unsigned plane = 0; plane < p; plane++) {
1241*61046927SAndroid Build Coastguard Worker          nvk_image_plane_add_req(dev, image, &image->planes[plane],
1242*61046927SAndroid Build Coastguard Worker                                  &offset_B, &align_B);
1243*61046927SAndroid Build Coastguard Worker       }
1244*61046927SAndroid Build Coastguard Worker    }
1245*61046927SAndroid Build Coastguard Worker    offset_B += nil_image_level_layer_offset_B(&plane->nil, isr->mipLevel,
1246*61046927SAndroid Build Coastguard Worker                                               isr->arrayLayer);
1247*61046927SAndroid Build Coastguard Worker 
1248*61046927SAndroid Build Coastguard Worker    pLayout->subresourceLayout = (VkSubresourceLayout) {
1249*61046927SAndroid Build Coastguard Worker       .offset = offset_B,
1250*61046927SAndroid Build Coastguard Worker       .size = nil_image_level_size_B(&plane->nil, isr->mipLevel),
1251*61046927SAndroid Build Coastguard Worker       .rowPitch = plane->nil.levels[isr->mipLevel].row_stride_B,
1252*61046927SAndroid Build Coastguard Worker       .arrayPitch = plane->nil.array_stride_B,
1253*61046927SAndroid Build Coastguard Worker       .depthPitch = nil_image_level_depth_stride_B(&plane->nil, isr->mipLevel),
1254*61046927SAndroid Build Coastguard Worker    };
1255*61046927SAndroid Build Coastguard Worker }
1256*61046927SAndroid Build Coastguard Worker 
1257*61046927SAndroid Build Coastguard Worker VKAPI_ATTR void VKAPI_CALL
nvk_GetImageSubresourceLayout2KHR(VkDevice device,VkImage _image,const VkImageSubresource2KHR * pSubresource,VkSubresourceLayout2KHR * pLayout)1258*61046927SAndroid Build Coastguard Worker nvk_GetImageSubresourceLayout2KHR(VkDevice device,
1259*61046927SAndroid Build Coastguard Worker                                   VkImage _image,
1260*61046927SAndroid Build Coastguard Worker                                   const VkImageSubresource2KHR *pSubresource,
1261*61046927SAndroid Build Coastguard Worker                                   VkSubresourceLayout2KHR *pLayout)
1262*61046927SAndroid Build Coastguard Worker {
1263*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(nvk_device, dev, device);
1264*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(nvk_image, image, _image);
1265*61046927SAndroid Build Coastguard Worker 
1266*61046927SAndroid Build Coastguard Worker    nvk_get_image_subresource_layout(dev, image, pSubresource, pLayout);
1267*61046927SAndroid Build Coastguard Worker }
1268*61046927SAndroid Build Coastguard Worker 
1269*61046927SAndroid Build Coastguard Worker VKAPI_ATTR void VKAPI_CALL
nvk_GetDeviceImageSubresourceLayoutKHR(VkDevice device,const VkDeviceImageSubresourceInfoKHR * pInfo,VkSubresourceLayout2KHR * pLayout)1270*61046927SAndroid Build Coastguard Worker nvk_GetDeviceImageSubresourceLayoutKHR(
1271*61046927SAndroid Build Coastguard Worker     VkDevice device,
1272*61046927SAndroid Build Coastguard Worker     const VkDeviceImageSubresourceInfoKHR *pInfo,
1273*61046927SAndroid Build Coastguard Worker     VkSubresourceLayout2KHR *pLayout)
1274*61046927SAndroid Build Coastguard Worker {
1275*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(nvk_device, dev, device);
1276*61046927SAndroid Build Coastguard Worker    ASSERTED VkResult result;
1277*61046927SAndroid Build Coastguard Worker    struct nvk_image image = {0};
1278*61046927SAndroid Build Coastguard Worker 
1279*61046927SAndroid Build Coastguard Worker    result = nvk_image_init(dev, &image, pInfo->pCreateInfo);
1280*61046927SAndroid Build Coastguard Worker    assert(result == VK_SUCCESS);
1281*61046927SAndroid Build Coastguard Worker 
1282*61046927SAndroid Build Coastguard Worker    nvk_get_image_subresource_layout(dev, &image, pInfo->pSubresource, pLayout);
1283*61046927SAndroid Build Coastguard Worker 
1284*61046927SAndroid Build Coastguard Worker    nvk_image_finish(dev, &image, NULL);
1285*61046927SAndroid Build Coastguard Worker }
1286*61046927SAndroid Build Coastguard Worker 
1287*61046927SAndroid Build Coastguard Worker static VkResult
nvk_image_plane_bind(struct nvk_device * dev,struct nvk_image * image,struct nvk_image_plane * plane,struct nvk_device_memory * mem,uint64_t * offset_B)1288*61046927SAndroid Build Coastguard Worker nvk_image_plane_bind(struct nvk_device *dev,
1289*61046927SAndroid Build Coastguard Worker                      struct nvk_image *image,
1290*61046927SAndroid Build Coastguard Worker                      struct nvk_image_plane *plane,
1291*61046927SAndroid Build Coastguard Worker                      struct nvk_device_memory *mem,
1292*61046927SAndroid Build Coastguard Worker                      uint64_t *offset_B)
1293*61046927SAndroid Build Coastguard Worker {
1294*61046927SAndroid Build Coastguard Worker    uint64_t plane_size_B, plane_align_B;
1295*61046927SAndroid Build Coastguard Worker    nvk_image_plane_size_align_B(dev, image, plane,
1296*61046927SAndroid Build Coastguard Worker                                 &plane_size_B, &plane_align_B);
1297*61046927SAndroid Build Coastguard Worker    *offset_B = align64(*offset_B, plane_align_B);
1298*61046927SAndroid Build Coastguard Worker 
1299*61046927SAndroid Build Coastguard Worker    if (plane->va != NULL) {
1300*61046927SAndroid Build Coastguard Worker       VkResult result = nvkmd_va_bind_mem(plane->va, &image->vk.base, 0,
1301*61046927SAndroid Build Coastguard Worker                                           mem->mem, *offset_B,
1302*61046927SAndroid Build Coastguard Worker                                           plane->va->size_B);
1303*61046927SAndroid Build Coastguard Worker       if (result != VK_SUCCESS)
1304*61046927SAndroid Build Coastguard Worker          return result;
1305*61046927SAndroid Build Coastguard Worker    } else {
1306*61046927SAndroid Build Coastguard Worker       assert(plane->nil.pte_kind == 0);
1307*61046927SAndroid Build Coastguard Worker       plane->addr = mem->mem->va->addr + *offset_B;
1308*61046927SAndroid Build Coastguard Worker    }
1309*61046927SAndroid Build Coastguard Worker 
1310*61046927SAndroid Build Coastguard Worker    *offset_B += plane_size_B;
1311*61046927SAndroid Build Coastguard Worker 
1312*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
1313*61046927SAndroid Build Coastguard Worker }
1314*61046927SAndroid Build Coastguard Worker 
1315*61046927SAndroid Build Coastguard Worker static VkResult
nvk_bind_image_memory(struct nvk_device * dev,const VkBindImageMemoryInfo * info)1316*61046927SAndroid Build Coastguard Worker nvk_bind_image_memory(struct nvk_device *dev,
1317*61046927SAndroid Build Coastguard Worker                       const VkBindImageMemoryInfo *info)
1318*61046927SAndroid Build Coastguard Worker {
1319*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(nvk_device_memory, mem, info->memory);
1320*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(nvk_image, image, info->image);
1321*61046927SAndroid Build Coastguard Worker    VkResult result;
1322*61046927SAndroid Build Coastguard Worker 
1323*61046927SAndroid Build Coastguard Worker    /* Ignore this struct on Android, we cannot access swapchain structures there. */
1324*61046927SAndroid Build Coastguard Worker #ifdef NVK_USE_WSI_PLATFORM
1325*61046927SAndroid Build Coastguard Worker    const VkBindImageMemorySwapchainInfoKHR *swapchain_info =
1326*61046927SAndroid Build Coastguard Worker       vk_find_struct_const(info->pNext, BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR);
1327*61046927SAndroid Build Coastguard Worker 
1328*61046927SAndroid Build Coastguard Worker    if (swapchain_info && swapchain_info->swapchain != VK_NULL_HANDLE) {
1329*61046927SAndroid Build Coastguard Worker       VkImage _wsi_image = wsi_common_get_image(swapchain_info->swapchain,
1330*61046927SAndroid Build Coastguard Worker                                                 swapchain_info->imageIndex);
1331*61046927SAndroid Build Coastguard Worker       VK_FROM_HANDLE(nvk_image, wsi_img, _wsi_image);
1332*61046927SAndroid Build Coastguard Worker 
1333*61046927SAndroid Build Coastguard Worker       assert(image->plane_count == 1);
1334*61046927SAndroid Build Coastguard Worker       assert(wsi_img->plane_count == 1);
1335*61046927SAndroid Build Coastguard Worker 
1336*61046927SAndroid Build Coastguard Worker       struct nvk_image_plane *plane = &image->planes[0];
1337*61046927SAndroid Build Coastguard Worker       struct nvk_image_plane *swapchain_plane = &wsi_img->planes[0];
1338*61046927SAndroid Build Coastguard Worker 
1339*61046927SAndroid Build Coastguard Worker       /* Copy memory binding information from swapchain image to the current image's plane. */
1340*61046927SAndroid Build Coastguard Worker       plane->addr = swapchain_plane->addr;
1341*61046927SAndroid Build Coastguard Worker 
1342*61046927SAndroid Build Coastguard Worker       return VK_SUCCESS;
1343*61046927SAndroid Build Coastguard Worker    }
1344*61046927SAndroid Build Coastguard Worker #endif
1345*61046927SAndroid Build Coastguard Worker 
1346*61046927SAndroid Build Coastguard Worker    uint64_t offset_B = info->memoryOffset;
1347*61046927SAndroid Build Coastguard Worker    if (image->disjoint) {
1348*61046927SAndroid Build Coastguard Worker       const VkBindImagePlaneMemoryInfo *plane_info =
1349*61046927SAndroid Build Coastguard Worker          vk_find_struct_const(info->pNext, BIND_IMAGE_PLANE_MEMORY_INFO);
1350*61046927SAndroid Build Coastguard Worker       const uint8_t plane =
1351*61046927SAndroid Build Coastguard Worker          nvk_image_memory_aspects_to_plane(image, plane_info->planeAspect);
1352*61046927SAndroid Build Coastguard Worker       result = nvk_image_plane_bind(dev, image, &image->planes[plane],
1353*61046927SAndroid Build Coastguard Worker                                     mem, &offset_B);
1354*61046927SAndroid Build Coastguard Worker       if (result != VK_SUCCESS)
1355*61046927SAndroid Build Coastguard Worker          return result;
1356*61046927SAndroid Build Coastguard Worker    } else {
1357*61046927SAndroid Build Coastguard Worker       for (unsigned plane = 0; plane < image->plane_count; plane++) {
1358*61046927SAndroid Build Coastguard Worker          result = nvk_image_plane_bind(dev, image, &image->planes[plane],
1359*61046927SAndroid Build Coastguard Worker                                        mem, &offset_B);
1360*61046927SAndroid Build Coastguard Worker          if (result != VK_SUCCESS)
1361*61046927SAndroid Build Coastguard Worker             return result;
1362*61046927SAndroid Build Coastguard Worker       }
1363*61046927SAndroid Build Coastguard Worker    }
1364*61046927SAndroid Build Coastguard Worker 
1365*61046927SAndroid Build Coastguard Worker    if (image->stencil_copy_temp.nil.size_B > 0) {
1366*61046927SAndroid Build Coastguard Worker       result = nvk_image_plane_bind(dev, image, &image->stencil_copy_temp,
1367*61046927SAndroid Build Coastguard Worker                                     mem, &offset_B);
1368*61046927SAndroid Build Coastguard Worker       if (result != VK_SUCCESS)
1369*61046927SAndroid Build Coastguard Worker          return result;
1370*61046927SAndroid Build Coastguard Worker    }
1371*61046927SAndroid Build Coastguard Worker 
1372*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
1373*61046927SAndroid Build Coastguard Worker }
1374*61046927SAndroid Build Coastguard Worker 
1375*61046927SAndroid Build Coastguard Worker VKAPI_ATTR VkResult VKAPI_CALL
nvk_BindImageMemory2(VkDevice device,uint32_t bindInfoCount,const VkBindImageMemoryInfo * pBindInfos)1376*61046927SAndroid Build Coastguard Worker nvk_BindImageMemory2(VkDevice device,
1377*61046927SAndroid Build Coastguard Worker                      uint32_t bindInfoCount,
1378*61046927SAndroid Build Coastguard Worker                      const VkBindImageMemoryInfo *pBindInfos)
1379*61046927SAndroid Build Coastguard Worker {
1380*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(nvk_device, dev, device);
1381*61046927SAndroid Build Coastguard Worker    VkResult first_error_or_success = VK_SUCCESS;
1382*61046927SAndroid Build Coastguard Worker 
1383*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < bindInfoCount; ++i) {
1384*61046927SAndroid Build Coastguard Worker       VkResult result = nvk_bind_image_memory(dev, &pBindInfos[i]);
1385*61046927SAndroid Build Coastguard Worker 
1386*61046927SAndroid Build Coastguard Worker       const VkBindMemoryStatusKHR *status =
1387*61046927SAndroid Build Coastguard Worker          vk_find_struct_const(pBindInfos[i].pNext, BIND_MEMORY_STATUS_KHR);
1388*61046927SAndroid Build Coastguard Worker       if (status != NULL && status->pResult != NULL)
1389*61046927SAndroid Build Coastguard Worker          *status->pResult = VK_SUCCESS;
1390*61046927SAndroid Build Coastguard Worker 
1391*61046927SAndroid Build Coastguard Worker       if (first_error_or_success == VK_SUCCESS)
1392*61046927SAndroid Build Coastguard Worker          first_error_or_success = result;
1393*61046927SAndroid Build Coastguard Worker    }
1394*61046927SAndroid Build Coastguard Worker 
1395*61046927SAndroid Build Coastguard Worker    return first_error_or_success;
1396*61046927SAndroid Build Coastguard Worker }
1397*61046927SAndroid Build Coastguard Worker 
1398*61046927SAndroid Build Coastguard Worker 
1399*61046927SAndroid Build Coastguard Worker static VkResult
queue_image_plane_bind(struct nvk_queue * queue,const struct nvk_image_plane * plane,const VkSparseImageMemoryBind * bind)1400*61046927SAndroid Build Coastguard Worker queue_image_plane_bind(struct nvk_queue *queue,
1401*61046927SAndroid Build Coastguard Worker                        const struct nvk_image_plane *plane,
1402*61046927SAndroid Build Coastguard Worker                        const VkSparseImageMemoryBind *bind)
1403*61046927SAndroid Build Coastguard Worker {
1404*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(nvk_device_memory, mem, bind->memory);
1405*61046927SAndroid Build Coastguard Worker    uint64_t image_bind_offset_B;
1406*61046927SAndroid Build Coastguard Worker 
1407*61046927SAndroid Build Coastguard Worker    const uint64_t mem_bind_offset_B = bind->memoryOffset;
1408*61046927SAndroid Build Coastguard Worker    const uint32_t layer = bind->subresource.arrayLayer;
1409*61046927SAndroid Build Coastguard Worker    const uint32_t level = bind->subresource.mipLevel;
1410*61046927SAndroid Build Coastguard Worker 
1411*61046927SAndroid Build Coastguard Worker    const struct nil_tiling plane_tiling = plane->nil.levels[level].tiling;
1412*61046927SAndroid Build Coastguard Worker    const uint32_t tile_size_B = nil_tiling_size_B(&plane_tiling);
1413*61046927SAndroid Build Coastguard Worker 
1414*61046927SAndroid Build Coastguard Worker    const struct nil_Extent4D_Pixels bind_extent_px = {
1415*61046927SAndroid Build Coastguard Worker       .width = bind->extent.width,
1416*61046927SAndroid Build Coastguard Worker       .height = bind->extent.height,
1417*61046927SAndroid Build Coastguard Worker       .depth = bind->extent.depth,
1418*61046927SAndroid Build Coastguard Worker       .array_len = 1,
1419*61046927SAndroid Build Coastguard Worker    };
1420*61046927SAndroid Build Coastguard Worker    const struct nil_Offset4D_Pixels bind_offset_px = {
1421*61046927SAndroid Build Coastguard Worker       .x = bind->offset.x,
1422*61046927SAndroid Build Coastguard Worker       .y = bind->offset.y,
1423*61046927SAndroid Build Coastguard Worker       .z = bind->offset.z,
1424*61046927SAndroid Build Coastguard Worker       .a = layer,
1425*61046927SAndroid Build Coastguard Worker    };
1426*61046927SAndroid Build Coastguard Worker 
1427*61046927SAndroid Build Coastguard Worker    const struct nil_Extent4D_Pixels level_extent_px =
1428*61046927SAndroid Build Coastguard Worker       nil_image_level_extent_px(&plane->nil, level);
1429*61046927SAndroid Build Coastguard Worker    const struct nil_Extent4D_Tiles level_extent_tl =
1430*61046927SAndroid Build Coastguard Worker       nil_extent4d_px_to_tl(level_extent_px, &plane_tiling,
1431*61046927SAndroid Build Coastguard Worker                             plane->nil.format,
1432*61046927SAndroid Build Coastguard Worker                             plane->nil.sample_layout);
1433*61046927SAndroid Build Coastguard Worker 
1434*61046927SAndroid Build Coastguard Worker    /* Convert the extent and offset to tiles */
1435*61046927SAndroid Build Coastguard Worker    const struct nil_Extent4D_Tiles bind_extent_tl =
1436*61046927SAndroid Build Coastguard Worker       nil_extent4d_px_to_tl(bind_extent_px, &plane_tiling,
1437*61046927SAndroid Build Coastguard Worker                             plane->nil.format,
1438*61046927SAndroid Build Coastguard Worker                             plane->nil.sample_layout);
1439*61046927SAndroid Build Coastguard Worker    const struct nil_Offset4D_Tiles bind_offset_tl =
1440*61046927SAndroid Build Coastguard Worker       nil_offset4d_px_to_tl(bind_offset_px, &plane_tiling,
1441*61046927SAndroid Build Coastguard Worker                             plane->nil.format,
1442*61046927SAndroid Build Coastguard Worker                             plane->nil.sample_layout);
1443*61046927SAndroid Build Coastguard Worker 
1444*61046927SAndroid Build Coastguard Worker    image_bind_offset_B =
1445*61046927SAndroid Build Coastguard Worker       nil_image_level_layer_offset_B(&plane->nil, level, layer);
1446*61046927SAndroid Build Coastguard Worker 
1447*61046927SAndroid Build Coastguard Worker    /* We can only bind contiguous ranges, so we'll split the image into rows
1448*61046927SAndroid Build Coastguard Worker     * of tiles that are guaranteed to be contiguous, and bind in terms of
1449*61046927SAndroid Build Coastguard Worker     * these rows
1450*61046927SAndroid Build Coastguard Worker     */
1451*61046927SAndroid Build Coastguard Worker 
1452*61046927SAndroid Build Coastguard Worker    /* First, get the size of the bind. Since we have the extent in terms of
1453*61046927SAndroid Build Coastguard Worker     * tiles already, we just need to multiply that by the tile size to get
1454*61046927SAndroid Build Coastguard Worker     * the size in bytes
1455*61046927SAndroid Build Coastguard Worker     */
1456*61046927SAndroid Build Coastguard Worker    uint64_t row_bind_size_B = bind_extent_tl.width * tile_size_B;
1457*61046927SAndroid Build Coastguard Worker 
1458*61046927SAndroid Build Coastguard Worker    const uint32_t nvkmd_bind_count = bind_extent_tl.depth *
1459*61046927SAndroid Build Coastguard Worker                                      bind_extent_tl.height;
1460*61046927SAndroid Build Coastguard Worker    STACK_ARRAY(struct nvkmd_ctx_bind, nvkmd_binds, nvkmd_bind_count);
1461*61046927SAndroid Build Coastguard Worker    uint32_t nvkmd_bind_idx = 0;
1462*61046927SAndroid Build Coastguard Worker 
1463*61046927SAndroid Build Coastguard Worker    /* Second, start walking the binding region in units of tiles, starting
1464*61046927SAndroid Build Coastguard Worker     * from the third dimension
1465*61046927SAndroid Build Coastguard Worker     */
1466*61046927SAndroid Build Coastguard Worker    for (uint32_t z_tl = 0; z_tl < bind_extent_tl.depth; z_tl++) {
1467*61046927SAndroid Build Coastguard Worker       /* Start walking the rows to be bound */
1468*61046927SAndroid Build Coastguard Worker       for (uint32_t y_tl = 0; y_tl < bind_extent_tl.height; y_tl++) {
1469*61046927SAndroid Build Coastguard Worker          /* For the bind offset, get a memory offset to the start of the row
1470*61046927SAndroid Build Coastguard Worker           * in terms of the bind extent
1471*61046927SAndroid Build Coastguard Worker           */
1472*61046927SAndroid Build Coastguard Worker          const uint64_t mem_row_start_tl =
1473*61046927SAndroid Build Coastguard Worker             y_tl * bind_extent_tl.width +
1474*61046927SAndroid Build Coastguard Worker             z_tl * bind_extent_tl.width * bind_extent_tl.height;
1475*61046927SAndroid Build Coastguard Worker 
1476*61046927SAndroid Build Coastguard Worker          const uint32_t image_x_tl = bind_offset_tl.x;
1477*61046927SAndroid Build Coastguard Worker          const uint32_t image_y_tl = bind_offset_tl.y + y_tl;
1478*61046927SAndroid Build Coastguard Worker          const uint32_t image_z_tl = bind_offset_tl.z + z_tl;
1479*61046927SAndroid Build Coastguard Worker 
1480*61046927SAndroid Build Coastguard Worker          /* The image offset is calculated in terms of the level extent */
1481*61046927SAndroid Build Coastguard Worker          const uint64_t image_row_start_tl =
1482*61046927SAndroid Build Coastguard Worker             image_x_tl +
1483*61046927SAndroid Build Coastguard Worker             image_y_tl * level_extent_tl.width +
1484*61046927SAndroid Build Coastguard Worker             image_z_tl * level_extent_tl.width * level_extent_tl.height;
1485*61046927SAndroid Build Coastguard Worker 
1486*61046927SAndroid Build Coastguard Worker          nvkmd_binds[nvkmd_bind_idx++] = (struct nvkmd_ctx_bind) {
1487*61046927SAndroid Build Coastguard Worker             .op = mem ? NVKMD_BIND_OP_BIND : NVKMD_BIND_OP_UNBIND,
1488*61046927SAndroid Build Coastguard Worker             .va = plane->va,
1489*61046927SAndroid Build Coastguard Worker             .va_offset_B = image_bind_offset_B +
1490*61046927SAndroid Build Coastguard Worker                            image_row_start_tl * tile_size_B,
1491*61046927SAndroid Build Coastguard Worker             .mem = mem ? mem->mem : NULL,
1492*61046927SAndroid Build Coastguard Worker             .mem_offset_B = mem_bind_offset_B +
1493*61046927SAndroid Build Coastguard Worker                             mem_row_start_tl * tile_size_B,
1494*61046927SAndroid Build Coastguard Worker             .range_B = row_bind_size_B,
1495*61046927SAndroid Build Coastguard Worker          };
1496*61046927SAndroid Build Coastguard Worker       }
1497*61046927SAndroid Build Coastguard Worker    }
1498*61046927SAndroid Build Coastguard Worker 
1499*61046927SAndroid Build Coastguard Worker    assert(nvkmd_bind_idx == nvkmd_bind_count);
1500*61046927SAndroid Build Coastguard Worker    VkResult result = nvkmd_ctx_bind(queue->bind_ctx, &queue->vk.base,
1501*61046927SAndroid Build Coastguard Worker                                     nvkmd_bind_count, nvkmd_binds);
1502*61046927SAndroid Build Coastguard Worker 
1503*61046927SAndroid Build Coastguard Worker    STACK_ARRAY_FINISH(nvkmd_binds);
1504*61046927SAndroid Build Coastguard Worker 
1505*61046927SAndroid Build Coastguard Worker    return result;
1506*61046927SAndroid Build Coastguard Worker }
1507*61046927SAndroid Build Coastguard Worker 
1508*61046927SAndroid Build Coastguard Worker VkResult
nvk_queue_image_bind(struct nvk_queue * queue,const VkSparseImageMemoryBindInfo * bind_info)1509*61046927SAndroid Build Coastguard Worker nvk_queue_image_bind(struct nvk_queue *queue,
1510*61046927SAndroid Build Coastguard Worker                      const VkSparseImageMemoryBindInfo *bind_info)
1511*61046927SAndroid Build Coastguard Worker {
1512*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(nvk_image, image, bind_info->image);
1513*61046927SAndroid Build Coastguard Worker    VkResult result;
1514*61046927SAndroid Build Coastguard Worker 
1515*61046927SAndroid Build Coastguard Worker    /* Sparse residency with multiplane is currently not supported */
1516*61046927SAndroid Build Coastguard Worker    assert(image->plane_count == 1);
1517*61046927SAndroid Build Coastguard Worker 
1518*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < bind_info->bindCount; i++) {
1519*61046927SAndroid Build Coastguard Worker       result = queue_image_plane_bind(queue, &image->planes[0],
1520*61046927SAndroid Build Coastguard Worker                                       &bind_info->pBinds[i]);
1521*61046927SAndroid Build Coastguard Worker       if (result != VK_SUCCESS)
1522*61046927SAndroid Build Coastguard Worker          return result;
1523*61046927SAndroid Build Coastguard Worker    }
1524*61046927SAndroid Build Coastguard Worker 
1525*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
1526*61046927SAndroid Build Coastguard Worker }
1527*61046927SAndroid Build Coastguard Worker 
1528*61046927SAndroid Build Coastguard Worker static bool
next_opaque_bind_plane(const VkSparseMemoryBind * bind,uint64_t size_B,uint32_t align_B,uint64_t * plane_offset_B,uint64_t * mem_offset_B,uint64_t * bind_size_B,uint64_t * image_plane_offset_B_iter)1529*61046927SAndroid Build Coastguard Worker next_opaque_bind_plane(const VkSparseMemoryBind *bind,
1530*61046927SAndroid Build Coastguard Worker                        uint64_t size_B, uint32_t align_B,
1531*61046927SAndroid Build Coastguard Worker                        uint64_t *plane_offset_B,
1532*61046927SAndroid Build Coastguard Worker                        uint64_t *mem_offset_B,
1533*61046927SAndroid Build Coastguard Worker                        uint64_t *bind_size_B,
1534*61046927SAndroid Build Coastguard Worker                        uint64_t *image_plane_offset_B_iter)
1535*61046927SAndroid Build Coastguard Worker {
1536*61046927SAndroid Build Coastguard Worker    /* Figure out the offset to thise plane and increment _iter up-front so
1537*61046927SAndroid Build Coastguard Worker     * that we're free to early return elsewhere in the function.
1538*61046927SAndroid Build Coastguard Worker     */
1539*61046927SAndroid Build Coastguard Worker    *image_plane_offset_B_iter = align64(*image_plane_offset_B_iter, align_B);
1540*61046927SAndroid Build Coastguard Worker    const uint64_t image_plane_offset_B = *image_plane_offset_B_iter;
1541*61046927SAndroid Build Coastguard Worker    *image_plane_offset_B_iter += size_B;
1542*61046927SAndroid Build Coastguard Worker 
1543*61046927SAndroid Build Coastguard Worker    /* Offset into the image or image mip tail, as appropriate */
1544*61046927SAndroid Build Coastguard Worker    uint64_t bind_offset_B = bind->resourceOffset;
1545*61046927SAndroid Build Coastguard Worker    if (bind_offset_B >= NVK_MIP_TAIL_START_OFFSET)
1546*61046927SAndroid Build Coastguard Worker       bind_offset_B -= NVK_MIP_TAIL_START_OFFSET;
1547*61046927SAndroid Build Coastguard Worker 
1548*61046927SAndroid Build Coastguard Worker    if (bind_offset_B < image_plane_offset_B) {
1549*61046927SAndroid Build Coastguard Worker       /* The offset of the plane within the bind */
1550*61046927SAndroid Build Coastguard Worker       const uint64_t bind_plane_offset_B =
1551*61046927SAndroid Build Coastguard Worker          image_plane_offset_B - bind_offset_B;
1552*61046927SAndroid Build Coastguard Worker 
1553*61046927SAndroid Build Coastguard Worker       /* If this plane lies above the bound range, skip this plane */
1554*61046927SAndroid Build Coastguard Worker       if (bind_plane_offset_B >= bind->size)
1555*61046927SAndroid Build Coastguard Worker          return false;
1556*61046927SAndroid Build Coastguard Worker 
1557*61046927SAndroid Build Coastguard Worker       *plane_offset_B = 0;
1558*61046927SAndroid Build Coastguard Worker       *mem_offset_B = bind->memoryOffset + bind_plane_offset_B;
1559*61046927SAndroid Build Coastguard Worker       *bind_size_B = MIN2(bind->size - bind_plane_offset_B, size_B);
1560*61046927SAndroid Build Coastguard Worker    } else {
1561*61046927SAndroid Build Coastguard Worker       /* The offset of the bind within the plane */
1562*61046927SAndroid Build Coastguard Worker       const uint64_t plane_bind_offset_B =
1563*61046927SAndroid Build Coastguard Worker          bind_offset_B - image_plane_offset_B;
1564*61046927SAndroid Build Coastguard Worker 
1565*61046927SAndroid Build Coastguard Worker       /* If this plane lies below the bound range, skip this plane */
1566*61046927SAndroid Build Coastguard Worker       if (plane_bind_offset_B >= size_B)
1567*61046927SAndroid Build Coastguard Worker          return false;
1568*61046927SAndroid Build Coastguard Worker 
1569*61046927SAndroid Build Coastguard Worker       *plane_offset_B = plane_bind_offset_B;
1570*61046927SAndroid Build Coastguard Worker       *mem_offset_B = bind->memoryOffset;
1571*61046927SAndroid Build Coastguard Worker       *bind_size_B = MIN2(bind->size, size_B - plane_bind_offset_B);
1572*61046927SAndroid Build Coastguard Worker    }
1573*61046927SAndroid Build Coastguard Worker 
1574*61046927SAndroid Build Coastguard Worker    return true;
1575*61046927SAndroid Build Coastguard Worker }
1576*61046927SAndroid Build Coastguard Worker 
1577*61046927SAndroid Build Coastguard Worker static VkResult
queue_image_plane_opaque_bind(struct nvk_queue * queue,struct nvk_image * image,struct nvk_image_plane * plane,const VkSparseMemoryBind * bind,uint64_t * image_plane_offset_B)1578*61046927SAndroid Build Coastguard Worker queue_image_plane_opaque_bind(struct nvk_queue *queue,
1579*61046927SAndroid Build Coastguard Worker                               struct nvk_image *image,
1580*61046927SAndroid Build Coastguard Worker                               struct nvk_image_plane *plane,
1581*61046927SAndroid Build Coastguard Worker                               const VkSparseMemoryBind *bind,
1582*61046927SAndroid Build Coastguard Worker                               uint64_t *image_plane_offset_B)
1583*61046927SAndroid Build Coastguard Worker {
1584*61046927SAndroid Build Coastguard Worker    uint64_t plane_size_B, plane_align_B;
1585*61046927SAndroid Build Coastguard Worker    nvk_image_plane_size_align_B(nvk_queue_device(queue), image, plane,
1586*61046927SAndroid Build Coastguard Worker                                 &plane_size_B, &plane_align_B);
1587*61046927SAndroid Build Coastguard Worker 
1588*61046927SAndroid Build Coastguard Worker    uint64_t plane_offset_B, mem_offset_B, bind_size_B;
1589*61046927SAndroid Build Coastguard Worker    if (!next_opaque_bind_plane(bind, plane_size_B, plane_align_B,
1590*61046927SAndroid Build Coastguard Worker                                &plane_offset_B, &mem_offset_B, &bind_size_B,
1591*61046927SAndroid Build Coastguard Worker                                image_plane_offset_B))
1592*61046927SAndroid Build Coastguard Worker       return VK_SUCCESS;
1593*61046927SAndroid Build Coastguard Worker 
1594*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(nvk_device_memory, mem, bind->memory);
1595*61046927SAndroid Build Coastguard Worker 
1596*61046927SAndroid Build Coastguard Worker    assert(plane_offset_B + bind_size_B <= plane->va->size_B);
1597*61046927SAndroid Build Coastguard Worker    assert(!mem || mem_offset_B + bind_size_B <= mem->vk.size);
1598*61046927SAndroid Build Coastguard Worker 
1599*61046927SAndroid Build Coastguard Worker    const struct nvkmd_ctx_bind nvkmd_bind = {
1600*61046927SAndroid Build Coastguard Worker       .op = mem ? NVKMD_BIND_OP_BIND : NVKMD_BIND_OP_UNBIND,
1601*61046927SAndroid Build Coastguard Worker       .va = plane->va,
1602*61046927SAndroid Build Coastguard Worker       .va_offset_B = plane_offset_B,
1603*61046927SAndroid Build Coastguard Worker       .mem = mem ? mem->mem : NULL,
1604*61046927SAndroid Build Coastguard Worker       .mem_offset_B = mem_offset_B,
1605*61046927SAndroid Build Coastguard Worker       .range_B = bind_size_B,
1606*61046927SAndroid Build Coastguard Worker    };
1607*61046927SAndroid Build Coastguard Worker    return nvkmd_ctx_bind(queue->bind_ctx, &queue->vk.base, 1, &nvkmd_bind);
1608*61046927SAndroid Build Coastguard Worker }
1609*61046927SAndroid Build Coastguard Worker 
1610*61046927SAndroid Build Coastguard Worker static VkResult
queue_image_plane_bind_mip_tail(struct nvk_queue * queue,struct nvk_image * image,struct nvk_image_plane * plane,const VkSparseMemoryBind * bind,uint64_t * image_plane_offset_B)1611*61046927SAndroid Build Coastguard Worker queue_image_plane_bind_mip_tail(struct nvk_queue *queue,
1612*61046927SAndroid Build Coastguard Worker                                 struct nvk_image *image,
1613*61046927SAndroid Build Coastguard Worker                                 struct nvk_image_plane *plane,
1614*61046927SAndroid Build Coastguard Worker                                 const VkSparseMemoryBind *bind,
1615*61046927SAndroid Build Coastguard Worker                                 uint64_t *image_plane_offset_B)
1616*61046927SAndroid Build Coastguard Worker {
1617*61046927SAndroid Build Coastguard Worker    uint64_t plane_size_B, plane_align_B;
1618*61046927SAndroid Build Coastguard Worker    nvk_image_plane_size_align_B(nvk_queue_device(queue), image, plane,
1619*61046927SAndroid Build Coastguard Worker                                 &plane_size_B, &plane_align_B);
1620*61046927SAndroid Build Coastguard Worker 
1621*61046927SAndroid Build Coastguard Worker    const uint64_t mip_tail_offset_B =
1622*61046927SAndroid Build Coastguard Worker       nil_image_mip_tail_offset_B(&plane->nil);
1623*61046927SAndroid Build Coastguard Worker    const uint64_t mip_tail_size_B =
1624*61046927SAndroid Build Coastguard Worker       nil_image_mip_tail_size_B(&plane->nil);
1625*61046927SAndroid Build Coastguard Worker    const uint64_t mip_tail_stride_B = plane->nil.array_stride_B;
1626*61046927SAndroid Build Coastguard Worker 
1627*61046927SAndroid Build Coastguard Worker    const uint64_t whole_mip_tail_size_B =
1628*61046927SAndroid Build Coastguard Worker       mip_tail_size_B * plane->nil.extent_px.array_len;
1629*61046927SAndroid Build Coastguard Worker 
1630*61046927SAndroid Build Coastguard Worker    uint64_t plane_offset_B, mem_offset_B, bind_size_B;
1631*61046927SAndroid Build Coastguard Worker    if (!next_opaque_bind_plane(bind, whole_mip_tail_size_B, plane_align_B,
1632*61046927SAndroid Build Coastguard Worker                                &plane_offset_B, &mem_offset_B, &bind_size_B,
1633*61046927SAndroid Build Coastguard Worker                                image_plane_offset_B))
1634*61046927SAndroid Build Coastguard Worker       return VK_SUCCESS;
1635*61046927SAndroid Build Coastguard Worker 
1636*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(nvk_device_memory, mem, bind->memory);
1637*61046927SAndroid Build Coastguard Worker 
1638*61046927SAndroid Build Coastguard Worker    /* Range within the virtual mip_tail space */
1639*61046927SAndroid Build Coastguard Worker    const uint64_t mip_bind_start_B = plane_offset_B;
1640*61046927SAndroid Build Coastguard Worker    const uint64_t mip_bind_end_B = mip_bind_start_B + bind_size_B;
1641*61046927SAndroid Build Coastguard Worker 
1642*61046927SAndroid Build Coastguard Worker    /* Range of array slices covered by this bind */
1643*61046927SAndroid Build Coastguard Worker    const uint32_t start_a = mip_bind_start_B / mip_tail_size_B;
1644*61046927SAndroid Build Coastguard Worker    const uint32_t end_a = DIV_ROUND_UP(mip_bind_end_B, mip_tail_size_B);
1645*61046927SAndroid Build Coastguard Worker 
1646*61046927SAndroid Build Coastguard Worker    const uint32_t nvkmd_bind_count = end_a - start_a;
1647*61046927SAndroid Build Coastguard Worker    STACK_ARRAY(struct nvkmd_ctx_bind, nvkmd_binds, nvkmd_bind_count);
1648*61046927SAndroid Build Coastguard Worker    uint32_t nvkmd_bind_idx = 0;
1649*61046927SAndroid Build Coastguard Worker 
1650*61046927SAndroid Build Coastguard Worker    for (uint32_t a = start_a; a < end_a; a++) {
1651*61046927SAndroid Build Coastguard Worker       /* Range within the virtual mip_tail space of this array slice */
1652*61046927SAndroid Build Coastguard Worker       const uint64_t a_mip_bind_start_B =
1653*61046927SAndroid Build Coastguard Worker          MAX2(a * mip_tail_size_B, mip_bind_start_B);
1654*61046927SAndroid Build Coastguard Worker       const uint64_t a_mip_bind_end_B =
1655*61046927SAndroid Build Coastguard Worker          MIN2((a + 1) * mip_tail_size_B, mip_bind_end_B);
1656*61046927SAndroid Build Coastguard Worker 
1657*61046927SAndroid Build Coastguard Worker       /* Offset and range within this mip_tail slice */
1658*61046927SAndroid Build Coastguard Worker       const uint64_t a_offset_B = a_mip_bind_start_B - a * mip_tail_size_B;
1659*61046927SAndroid Build Coastguard Worker       const uint64_t a_range_B = a_mip_bind_end_B - a_mip_bind_start_B;
1660*61046927SAndroid Build Coastguard Worker 
1661*61046927SAndroid Build Coastguard Worker       /* Offset within the current bind operation */
1662*61046927SAndroid Build Coastguard Worker       const uint64_t a_bind_offset_B =
1663*61046927SAndroid Build Coastguard Worker          a_mip_bind_start_B - mip_bind_start_B;
1664*61046927SAndroid Build Coastguard Worker 
1665*61046927SAndroid Build Coastguard Worker       /* Offset within the image */
1666*61046927SAndroid Build Coastguard Worker       const uint64_t a_image_offset_B =
1667*61046927SAndroid Build Coastguard Worker          mip_tail_offset_B + (a * mip_tail_stride_B) + a_offset_B;
1668*61046927SAndroid Build Coastguard Worker 
1669*61046927SAndroid Build Coastguard Worker       nvkmd_binds[nvkmd_bind_idx++] = (struct nvkmd_ctx_bind) {
1670*61046927SAndroid Build Coastguard Worker          .op = mem ? NVKMD_BIND_OP_BIND : NVKMD_BIND_OP_UNBIND,
1671*61046927SAndroid Build Coastguard Worker          .va = plane->va,
1672*61046927SAndroid Build Coastguard Worker          .va_offset_B = a_image_offset_B,
1673*61046927SAndroid Build Coastguard Worker          .mem = mem ? mem->mem : NULL,
1674*61046927SAndroid Build Coastguard Worker          .mem_offset_B = mem_offset_B + a_bind_offset_B,
1675*61046927SAndroid Build Coastguard Worker          .range_B = a_range_B,
1676*61046927SAndroid Build Coastguard Worker       };
1677*61046927SAndroid Build Coastguard Worker    }
1678*61046927SAndroid Build Coastguard Worker 
1679*61046927SAndroid Build Coastguard Worker    assert(nvkmd_bind_idx == nvkmd_bind_count);
1680*61046927SAndroid Build Coastguard Worker    VkResult result = nvkmd_ctx_bind(queue->bind_ctx, &queue->vk.base,
1681*61046927SAndroid Build Coastguard Worker                                     nvkmd_bind_count, nvkmd_binds);
1682*61046927SAndroid Build Coastguard Worker 
1683*61046927SAndroid Build Coastguard Worker    STACK_ARRAY_FINISH(nvkmd_binds);
1684*61046927SAndroid Build Coastguard Worker 
1685*61046927SAndroid Build Coastguard Worker    return result;
1686*61046927SAndroid Build Coastguard Worker }
1687*61046927SAndroid Build Coastguard Worker 
1688*61046927SAndroid Build Coastguard Worker VkResult
nvk_queue_image_opaque_bind(struct nvk_queue * queue,const VkSparseImageOpaqueMemoryBindInfo * bind_info)1689*61046927SAndroid Build Coastguard Worker nvk_queue_image_opaque_bind(struct nvk_queue *queue,
1690*61046927SAndroid Build Coastguard Worker                             const VkSparseImageOpaqueMemoryBindInfo *bind_info)
1691*61046927SAndroid Build Coastguard Worker {
1692*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(nvk_image, image, bind_info->image);
1693*61046927SAndroid Build Coastguard Worker    VkResult result;
1694*61046927SAndroid Build Coastguard Worker 
1695*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < bind_info->bindCount; i++) {
1696*61046927SAndroid Build Coastguard Worker       const VkSparseMemoryBind *bind = &bind_info->pBinds[i];
1697*61046927SAndroid Build Coastguard Worker 
1698*61046927SAndroid Build Coastguard Worker       uint64_t image_plane_offset_B = 0;
1699*61046927SAndroid Build Coastguard Worker       for (unsigned plane = 0; plane < image->plane_count; plane++) {
1700*61046927SAndroid Build Coastguard Worker          if (bind->resourceOffset >= NVK_MIP_TAIL_START_OFFSET) {
1701*61046927SAndroid Build Coastguard Worker             result = queue_image_plane_bind_mip_tail(queue, image,
1702*61046927SAndroid Build Coastguard Worker                                                      &image->planes[plane],
1703*61046927SAndroid Build Coastguard Worker                                                      bind,
1704*61046927SAndroid Build Coastguard Worker                                                      &image_plane_offset_B);
1705*61046927SAndroid Build Coastguard Worker          } else {
1706*61046927SAndroid Build Coastguard Worker             result = queue_image_plane_opaque_bind(queue, image,
1707*61046927SAndroid Build Coastguard Worker                                                    &image->planes[plane],
1708*61046927SAndroid Build Coastguard Worker                                                    bind,
1709*61046927SAndroid Build Coastguard Worker                                                    &image_plane_offset_B);
1710*61046927SAndroid Build Coastguard Worker          }
1711*61046927SAndroid Build Coastguard Worker          if (result != VK_SUCCESS)
1712*61046927SAndroid Build Coastguard Worker             return result;
1713*61046927SAndroid Build Coastguard Worker       }
1714*61046927SAndroid Build Coastguard Worker       if (image->stencil_copy_temp.nil.size_B > 0) {
1715*61046927SAndroid Build Coastguard Worker          result = queue_image_plane_opaque_bind(queue, image,
1716*61046927SAndroid Build Coastguard Worker                                                 &image->stencil_copy_temp,
1717*61046927SAndroid Build Coastguard Worker                                                 bind,
1718*61046927SAndroid Build Coastguard Worker                                                 &image_plane_offset_B);
1719*61046927SAndroid Build Coastguard Worker          if (result != VK_SUCCESS)
1720*61046927SAndroid Build Coastguard Worker             return result;
1721*61046927SAndroid Build Coastguard Worker       }
1722*61046927SAndroid Build Coastguard Worker    }
1723*61046927SAndroid Build Coastguard Worker 
1724*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
1725*61046927SAndroid Build Coastguard Worker }
1726*61046927SAndroid Build Coastguard Worker 
1727*61046927SAndroid Build Coastguard Worker VKAPI_ATTR VkResult VKAPI_CALL
nvk_GetImageOpaqueCaptureDescriptorDataEXT(VkDevice _device,const VkImageCaptureDescriptorDataInfoEXT * pInfo,void * pData)1728*61046927SAndroid Build Coastguard Worker nvk_GetImageOpaqueCaptureDescriptorDataEXT(
1729*61046927SAndroid Build Coastguard Worker     VkDevice _device,
1730*61046927SAndroid Build Coastguard Worker     const VkImageCaptureDescriptorDataInfoEXT *pInfo,
1731*61046927SAndroid Build Coastguard Worker     void *pData)
1732*61046927SAndroid Build Coastguard Worker {
1733*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
1734*61046927SAndroid Build Coastguard Worker }
1735