• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2022 Collabora Ltd. and Red Hat Inc.
3  * SPDX-License-Identifier: MIT
4  */
5 #include "nvk_image.h"
6 
7 #include "nvk_device.h"
8 #include "nvk_device_memory.h"
9 #include "nvk_entrypoints.h"
10 #include "nvk_format.h"
11 #include "nvk_physical_device.h"
12 
13 #include "nil_format.h"
14 #include "vulkan/util/vk_format.h"
15 
16 #include "clb097.h"
17 #include "clb197.h"
18 
19 static VkFormatFeatureFlags2
nvk_get_image_plane_format_features(struct nvk_physical_device * pdev,VkFormat vk_format,VkImageTiling tiling)20 nvk_get_image_plane_format_features(struct nvk_physical_device *pdev,
21                                     VkFormat vk_format, VkImageTiling tiling)
22 {
23    VkFormatFeatureFlags2 features = 0;
24 
25    enum pipe_format p_format = vk_format_to_pipe_format(vk_format);
26    if (p_format == PIPE_FORMAT_NONE)
27       return 0;
28 
29    /* You can't tile a non-power-of-two */
30    if (!util_is_power_of_two_nonzero(util_format_get_blocksize(p_format)))
31       return 0;
32 
33    if (nil_format_supports_texturing(&pdev->info, p_format)) {
34       features |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT;
35       features |= VK_FORMAT_FEATURE_2_BLIT_SRC_BIT;
36    }
37 
38    if (nil_format_supports_filtering(&pdev->info, p_format)) {
39       features |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
40       if (pdev->info.cls_eng3d >= MAXWELL_B)
41          features |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_MINMAX_BIT;
42    }
43 
44    /* TODO: VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT */
45    if (vk_format_has_depth(vk_format)) {
46       features |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT;
47    }
48 
49    if (nil_format_supports_color_targets(&pdev->info, p_format) &&
50        tiling != VK_IMAGE_TILING_LINEAR) {
51       features |= VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT;
52       if (nil_format_supports_blending(&pdev->info, p_format))
53          features |= VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BLEND_BIT;
54       features |= VK_FORMAT_FEATURE_2_BLIT_DST_BIT;
55    }
56 
57    if (vk_format_is_depth_or_stencil(vk_format)) {
58       if (!nil_format_supports_depth_stencil(&pdev->info, p_format) ||
59           tiling == VK_IMAGE_TILING_LINEAR)
60          return 0;
61 
62       features |= VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT;
63    }
64 
65    if (nil_format_supports_storage(&pdev->info, p_format)) {
66       features |= VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT |
67                   VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT;
68       if (pdev->info.cls_eng3d >= MAXWELL_A)
69          features |= VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT;
70    }
71 
72    if (p_format == PIPE_FORMAT_R32_UINT || p_format == PIPE_FORMAT_R32_SINT ||
73        p_format == PIPE_FORMAT_R64_UINT || p_format == PIPE_FORMAT_R64_SINT)
74       features |= VK_FORMAT_FEATURE_2_STORAGE_IMAGE_ATOMIC_BIT;
75 
76    if (features != 0) {
77       features |= VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT;
78       features |= VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT;
79    }
80 
81    return features;
82 }
83 
84 VkFormatFeatureFlags2
nvk_get_image_format_features(struct nvk_physical_device * pdev,VkFormat vk_format,VkImageTiling tiling)85 nvk_get_image_format_features(struct nvk_physical_device *pdev,
86                               VkFormat vk_format, VkImageTiling tiling)
87 {
88    const struct vk_format_ycbcr_info *ycbcr_info =
89          vk_format_get_ycbcr_info(vk_format);
90    if (ycbcr_info == NULL)
91       return nvk_get_image_plane_format_features(pdev, vk_format, tiling);
92 
93    /* For multi-plane, we get the feature flags of each plane separately,
94     * then take their intersection as the overall format feature flags
95     */
96    VkFormatFeatureFlags2 features = ~0ull;
97    bool cosited_chroma = false;
98    for (uint8_t plane = 0; plane < ycbcr_info->n_planes; plane++) {
99       const struct vk_format_ycbcr_plane *plane_info = &ycbcr_info->planes[plane];
100       features &= nvk_get_image_plane_format_features(pdev, plane_info->format,
101                                                       tiling);
102       if (plane_info->denominator_scales[0] > 1 ||
103           plane_info->denominator_scales[1] > 1)
104          cosited_chroma = true;
105    }
106    if (features == 0)
107       return 0;
108 
109    /* Uh... We really should be able to sample from YCbCr */
110    assert(features & VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT);
111    assert(features & VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_LINEAR_BIT);
112 
113    /* These aren't allowed for YCbCr formats */
114    features &= ~(VK_FORMAT_FEATURE_2_BLIT_SRC_BIT |
115                  VK_FORMAT_FEATURE_2_BLIT_DST_BIT |
116                  VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT |
117                  VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BLEND_BIT |
118                  VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT);
119 
120    /* This is supported on all YCbCr formats */
121    features |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT;
122 
123    if (ycbcr_info->n_planes > 1) {
124       /* DISJOINT_BIT implies that each plane has its own separate binding,
125        * while SEPARATE_RECONSTRUCTION_FILTER_BIT implies that luma and chroma
126        * each have their own, separate filters, so these two bits make sense
127        * for multi-planar formats only.
128        *
129        * For MIDPOINT_CHROMA_SAMPLES_BIT, NVIDIA HW on single-plane interleaved
130        * YCbCr defaults to COSITED_EVEN, which is inaccurate and fails tests.
131        * This can be fixed with a NIR tweak but for now, we only enable this bit
132        * for multi-plane formats. See Issue #9525 on the mesa/main tracker.
133        */
134       features |= VK_FORMAT_FEATURE_DISJOINT_BIT |
135                   VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT |
136                   VK_FORMAT_FEATURE_2_MIDPOINT_CHROMA_SAMPLES_BIT;
137    }
138 
139    if (cosited_chroma)
140       features |= VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT;
141 
142    return features;
143 }
144 
145 static VkFormatFeatureFlags2
vk_image_usage_to_format_features(VkImageUsageFlagBits usage_flag)146 vk_image_usage_to_format_features(VkImageUsageFlagBits usage_flag)
147 {
148    assert(util_bitcount(usage_flag) == 1);
149    switch (usage_flag) {
150    case VK_IMAGE_USAGE_TRANSFER_SRC_BIT:
151       return VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT |
152              VK_FORMAT_FEATURE_BLIT_SRC_BIT;
153    case VK_IMAGE_USAGE_TRANSFER_DST_BIT:
154       return VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT |
155              VK_FORMAT_FEATURE_BLIT_DST_BIT;
156    case VK_IMAGE_USAGE_SAMPLED_BIT:
157       return VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT;
158    case VK_IMAGE_USAGE_STORAGE_BIT:
159       return VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT;
160    case VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT:
161       return VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT;
162    case VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT:
163       return VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT;
164    default:
165       return 0;
166    }
167 }
168 
169 uint32_t
nvk_image_max_dimension(const struct nv_device_info * info,VkImageType image_type)170 nvk_image_max_dimension(const struct nv_device_info *info,
171                         VkImageType image_type)
172 {
173    switch (image_type) {
174    case VK_IMAGE_TYPE_1D:
175    case VK_IMAGE_TYPE_2D:
176       return info->chipset >= 0x130 ? 0x8000 : 0x4000;
177    case VK_IMAGE_TYPE_3D:
178       return 0x4000;
179    default:
180       unreachable("Invalid image type");
181    }
182 }
183 
184 VKAPI_ATTR VkResult VKAPI_CALL
nvk_GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceImageFormatInfo2 * pImageFormatInfo,VkImageFormatProperties2 * pImageFormatProperties)185 nvk_GetPhysicalDeviceImageFormatProperties2(
186    VkPhysicalDevice physicalDevice,
187    const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo,
188    VkImageFormatProperties2 *pImageFormatProperties)
189 {
190    VK_FROM_HANDLE(nvk_physical_device, pdev, physicalDevice);
191 
192    const VkPhysicalDeviceExternalImageFormatInfo *external_info =
193       vk_find_struct_const(pImageFormatInfo->pNext,
194                            PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO);
195 
196    /* Initialize to zero in case we return VK_ERROR_FORMAT_NOT_SUPPORTED */
197    memset(&pImageFormatProperties->imageFormatProperties, 0,
198           sizeof(pImageFormatProperties->imageFormatProperties));
199 
200    const struct vk_format_ycbcr_info *ycbcr_info =
201       vk_format_get_ycbcr_info(pImageFormatInfo->format);
202 
203    /* For the purposes of these checks, we don't care about all the extra
204     * YCbCr features and we just want the accumulation of features available
205     * to all planes of the given format.
206     */
207    VkFormatFeatureFlags2 features;
208    if (ycbcr_info == NULL) {
209       features = nvk_get_image_plane_format_features(
210          pdev, pImageFormatInfo->format, pImageFormatInfo->tiling);
211    } else {
212       features = ~0ull;
213       assert(ycbcr_info->n_planes > 0);
214       for (uint8_t plane = 0; plane < ycbcr_info->n_planes; plane++) {
215          const VkFormat plane_format = ycbcr_info->planes[plane].format;
216          features &= nvk_get_image_plane_format_features(
217             pdev, plane_format, pImageFormatInfo->tiling);
218       }
219    }
220    if (features == 0)
221       return VK_ERROR_FORMAT_NOT_SUPPORTED;
222 
223    if (pImageFormatInfo->tiling == VK_IMAGE_TILING_LINEAR &&
224        pImageFormatInfo->type != VK_IMAGE_TYPE_2D)
225       return VK_ERROR_FORMAT_NOT_SUPPORTED;
226 
227    if (ycbcr_info && pImageFormatInfo->type != VK_IMAGE_TYPE_2D)
228       return VK_ERROR_FORMAT_NOT_SUPPORTED;
229 
230    const uint32_t max_dim =
231       nvk_image_max_dimension(&pdev->info, VK_IMAGE_TYPE_1D);
232    VkExtent3D maxExtent;
233    uint32_t maxArraySize;
234    switch (pImageFormatInfo->type) {
235    case VK_IMAGE_TYPE_1D:
236       maxExtent = (VkExtent3D) { max_dim, 1, 1 };
237       maxArraySize = 2048;
238       break;
239    case VK_IMAGE_TYPE_2D:
240       maxExtent = (VkExtent3D) { max_dim, max_dim, 1 };
241       maxArraySize = 2048;
242       break;
243    case VK_IMAGE_TYPE_3D:
244       maxExtent = (VkExtent3D) { max_dim, max_dim, max_dim };
245       maxArraySize = 1;
246       break;
247    default:
248       unreachable("Invalid image type");
249    }
250    if (pImageFormatInfo->tiling == VK_IMAGE_TILING_LINEAR)
251       maxArraySize = 1;
252 
253    assert(util_is_power_of_two_nonzero(max_dim));
254    uint32_t maxMipLevels = util_logbase2(max_dim) + 1;
255    if (ycbcr_info != NULL || pImageFormatInfo->tiling == VK_IMAGE_TILING_LINEAR)
256        maxMipLevels = 1;
257 
258    VkSampleCountFlags sampleCounts = VK_SAMPLE_COUNT_1_BIT;
259    if (pImageFormatInfo->tiling == VK_IMAGE_TILING_OPTIMAL &&
260        pImageFormatInfo->type == VK_IMAGE_TYPE_2D &&
261        ycbcr_info == NULL &&
262        (features & (VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT |
263                     VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT)) &&
264        !(pImageFormatInfo->flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) &&
265        !(pImageFormatInfo->usage & VK_IMAGE_USAGE_STORAGE_BIT)) {
266       sampleCounts = VK_SAMPLE_COUNT_1_BIT |
267                      VK_SAMPLE_COUNT_2_BIT |
268                      VK_SAMPLE_COUNT_4_BIT |
269                      VK_SAMPLE_COUNT_8_BIT;
270    }
271 
272    /* From the Vulkan 1.2.199 spec:
273     *
274     *    "VK_IMAGE_CREATE_EXTENDED_USAGE_BIT specifies that the image can be
275     *    created with usage flags that are not supported for the format the
276     *    image is created with but are supported for at least one format a
277     *    VkImageView created from the image can have."
278     *
279     * If VK_IMAGE_CREATE_EXTENDED_USAGE_BIT is set, views can be created with
280     * different usage than the image so we can't always filter on usage.
281     * There is one exception to this below for storage.
282     */
283    const VkImageUsageFlags image_usage = pImageFormatInfo->usage;
284    VkImageUsageFlags view_usage = image_usage;
285    if (pImageFormatInfo->flags & VK_IMAGE_CREATE_EXTENDED_USAGE_BIT)
286       view_usage = 0;
287 
288    u_foreach_bit(b, view_usage) {
289       VkFormatFeatureFlags2 usage_features =
290          vk_image_usage_to_format_features(1 << b);
291       if (usage_features && !(features & usage_features))
292          return VK_ERROR_FORMAT_NOT_SUPPORTED;
293    }
294 
295    const VkExternalMemoryProperties *ext_mem_props = NULL;
296    if (external_info != NULL && external_info->handleType != 0) {
297       bool tiling_has_explicit_layout;
298       switch (pImageFormatInfo->tiling) {
299       case VK_IMAGE_TILING_LINEAR:
300       case VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT:
301          tiling_has_explicit_layout = true;
302          break;
303       case VK_IMAGE_TILING_OPTIMAL:
304          tiling_has_explicit_layout = false;
305          break;
306       default:
307          unreachable("Unsupported VkImageTiling");
308       }
309 
310       switch (external_info->handleType) {
311       case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
312          /* No special restrictions */
313          if (tiling_has_explicit_layout) {
314             /* With an explicit memory layout, we don't care which type of
315              * fd the image belongs too. Both OPAQUE_FD and DMA_BUF are
316              * interchangeable here.
317              */
318             ext_mem_props = &nvk_dma_buf_mem_props;
319          } else {
320             ext_mem_props = &nvk_opaque_fd_mem_props;
321          }
322          break;
323 
324       case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
325          if (!tiling_has_explicit_layout) {
326             return vk_errorf(pdev, VK_ERROR_FORMAT_NOT_SUPPORTED,
327                              "VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT "
328                              "requires VK_IMAGE_TILING_LINEAR or "
329                              "VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT");
330          }
331          ext_mem_props = &nvk_dma_buf_mem_props;
332          break;
333 
334       default:
335          /* From the Vulkan 1.3.256 spec:
336           *
337           *    "If handleType is not compatible with the [parameters] in
338           *    VkPhysicalDeviceImageFormatInfo2, then
339           *    vkGetPhysicalDeviceImageFormatProperties2 returns
340           *    VK_ERROR_FORMAT_NOT_SUPPORTED."
341           */
342          return vk_errorf(pdev, VK_ERROR_FORMAT_NOT_SUPPORTED,
343                           "unsupported VkExternalMemoryTypeFlagBits 0x%x",
344                           external_info->handleType);
345       }
346    }
347 
348    const unsigned plane_count =
349       vk_format_get_plane_count(pImageFormatInfo->format);
350 
351    /* From the Vulkan 1.3.259 spec, VkImageCreateInfo:
352     *
353     *    VUID-VkImageCreateInfo-imageCreateFormatFeatures-02260
354     *
355     *    "If format is a multi-planar format, and if imageCreateFormatFeatures
356     *    (as defined in Image Creation Limits) does not contain
357     *    VK_FORMAT_FEATURE_DISJOINT_BIT, then flags must not contain
358     *    VK_IMAGE_CREATE_DISJOINT_BIT"
359     *
360     * This is satisfied trivially because we support DISJOINT on all
361     * multi-plane formats.  Also,
362     *
363     *    VUID-VkImageCreateInfo-format-01577
364     *
365     *    "If format is not a multi-planar format, and flags does not include
366     *    VK_IMAGE_CREATE_ALIAS_BIT, flags must not contain
367     *    VK_IMAGE_CREATE_DISJOINT_BIT"
368     */
369    if (plane_count == 1 &&
370        !(pImageFormatInfo->flags & VK_IMAGE_CREATE_ALIAS_BIT) &&
371        (pImageFormatInfo->flags & VK_IMAGE_CREATE_DISJOINT_BIT))
372       return VK_ERROR_FORMAT_NOT_SUPPORTED;
373 
374    pImageFormatProperties->imageFormatProperties = (VkImageFormatProperties) {
375       .maxExtent = maxExtent,
376       .maxMipLevels = maxMipLevels,
377       .maxArrayLayers = maxArraySize,
378       .sampleCounts = sampleCounts,
379       .maxResourceSize = UINT32_MAX, /* TODO */
380    };
381 
382    vk_foreach_struct(s, pImageFormatProperties->pNext) {
383       switch (s->sType) {
384       case VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES: {
385          VkExternalImageFormatProperties *p = (void *)s;
386          /* From the Vulkan 1.3.256 spec:
387           *
388           *    "If handleType is 0, vkGetPhysicalDeviceImageFormatProperties2
389           *    will behave as if VkPhysicalDeviceExternalImageFormatInfo was
390           *    not present, and VkExternalImageFormatProperties will be
391           *    ignored."
392           *
393           * This is true if and only if ext_mem_props == NULL
394           */
395          if (ext_mem_props != NULL)
396             p->externalMemoryProperties = *ext_mem_props;
397          break;
398       }
399       case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES: {
400          VkSamplerYcbcrConversionImageFormatProperties *ycbcr_props = (void *) s;
401          ycbcr_props->combinedImageSamplerDescriptorCount = plane_count;
402          break;
403       }
404       default:
405          nvk_debug_ignored_stype(s->sType);
406          break;
407       }
408    }
409 
410    return VK_SUCCESS;
411 }
412 
413 VKAPI_ATTR void VKAPI_CALL
nvk_GetPhysicalDeviceSparseImageFormatProperties2(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceSparseImageFormatInfo2 * pFormatInfo,uint32_t * pPropertyCount,VkSparseImageFormatProperties2 * pProperties)414 nvk_GetPhysicalDeviceSparseImageFormatProperties2(
415     VkPhysicalDevice physicalDevice,
416     const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo,
417     uint32_t *pPropertyCount,
418     VkSparseImageFormatProperties2 *pProperties)
419 {
420    /* Sparse images are not yet supported. */
421    *pPropertyCount = 0;
422 }
423 
424 static enum nil_image_dim
vk_image_type_to_nil_dim(VkImageType type)425 vk_image_type_to_nil_dim(VkImageType type)
426 {
427    switch (type) {
428    case VK_IMAGE_TYPE_1D:  return NIL_IMAGE_DIM_1D;
429    case VK_IMAGE_TYPE_2D:  return NIL_IMAGE_DIM_2D;
430    case VK_IMAGE_TYPE_3D:  return NIL_IMAGE_DIM_3D;
431    default:
432       unreachable("Invalid image type");
433    }
434 }
435 
436 static VkResult
nvk_image_init(struct nvk_device * dev,struct nvk_image * image,const VkImageCreateInfo * pCreateInfo)437 nvk_image_init(struct nvk_device *dev,
438                struct nvk_image *image,
439                const VkImageCreateInfo *pCreateInfo)
440 {
441    vk_image_init(&dev->vk, &image->vk, pCreateInfo);
442 
443    if ((image->vk.usage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
444                            VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) &&
445        image->vk.samples > 1) {
446       image->vk.usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
447       image->vk.stencil_usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
448    }
449 
450    if (image->vk.usage & VK_IMAGE_USAGE_TRANSFER_SRC_BIT)
451       image->vk.usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
452    if (image->vk.usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT)
453       image->vk.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
454 
455    enum nil_image_usage_flags usage = 0; /* TODO */
456    if (pCreateInfo->tiling == VK_IMAGE_TILING_LINEAR)
457       usage |= NIL_IMAGE_USAGE_LINEAR_BIT;
458    if (pCreateInfo->flags & VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT)
459       usage |= NIL_IMAGE_USAGE_2D_VIEW_BIT;
460    if (pCreateInfo->flags & VK_IMAGE_CREATE_2D_VIEW_COMPATIBLE_BIT_EXT)
461       usage |= NIL_IMAGE_USAGE_2D_VIEW_BIT;
462 
463    /* We treat 3D storage images as 2D arrays.  One day, we may wire up actual
464     * 3D storage image support but baseArrayLayer gets tricky.
465     */
466    if (image->vk.usage & VK_IMAGE_USAGE_STORAGE_BIT)
467       usage |= NIL_IMAGE_USAGE_2D_VIEW_BIT;
468 
469    /* In order to be able to clear 3D depth/stencil images, we need to bind
470     * them as 2D arrays.  Fortunately, 3D depth/stencil shouldn't be common.
471     */
472    if ((image->vk.aspects & (VK_IMAGE_ASPECT_DEPTH_BIT |
473                              VK_IMAGE_ASPECT_STENCIL_BIT)) &&
474        pCreateInfo->imageType == VK_IMAGE_TYPE_3D)
475       usage |= NIL_IMAGE_USAGE_2D_VIEW_BIT;
476 
477    image->plane_count = vk_format_get_plane_count(pCreateInfo->format);
478    image->disjoint = image->plane_count > 1 &&
479                      (pCreateInfo->flags & VK_IMAGE_CREATE_DISJOINT_BIT);
480 
481    const struct vk_format_ycbcr_info *ycbcr_info =
482       vk_format_get_ycbcr_info(pCreateInfo->format);
483    for (uint8_t plane = 0; plane < image->plane_count; plane++) {
484       VkFormat format = ycbcr_info ?
485          ycbcr_info->planes[plane].format : pCreateInfo->format;
486       const uint8_t width_scale = ycbcr_info ?
487          ycbcr_info->planes[plane].denominator_scales[0] : 1;
488       const uint8_t height_scale = ycbcr_info ?
489          ycbcr_info->planes[plane].denominator_scales[1] : 1;
490       struct nil_image_init_info nil_info = {
491          .dim = vk_image_type_to_nil_dim(pCreateInfo->imageType),
492          .format = vk_format_to_pipe_format(format),
493          .extent_px = {
494             .w = pCreateInfo->extent.width / width_scale,
495             .h = pCreateInfo->extent.height / height_scale,
496             .d = pCreateInfo->extent.depth,
497             .a = pCreateInfo->arrayLayers,
498          },
499          .levels = pCreateInfo->mipLevels,
500          .samples = pCreateInfo->samples,
501          .usage = usage,
502       };
503 
504       ASSERTED bool ok = nil_image_init(&nvk_device_physical(dev)->info,
505                                         &image->planes[plane].nil, &nil_info);
506       assert(ok);
507    }
508 
509    if (image->vk.format == VK_FORMAT_D32_SFLOAT_S8_UINT) {
510       struct nil_image_init_info stencil_nil_info = {
511          .dim = vk_image_type_to_nil_dim(pCreateInfo->imageType),
512          .format = PIPE_FORMAT_R32_UINT,
513          .extent_px = {
514             .w = pCreateInfo->extent.width,
515             .h = pCreateInfo->extent.height,
516             .d = pCreateInfo->extent.depth,
517             .a = pCreateInfo->arrayLayers,
518          },
519          .levels = pCreateInfo->mipLevels,
520          .samples = pCreateInfo->samples,
521          .usage = usage,
522       };
523 
524       ASSERTED bool ok = nil_image_init(&nvk_device_physical(dev)->info,
525                                         &image->stencil_copy_temp.nil,
526                                         &stencil_nil_info);
527       assert(ok);
528    }
529 
530    return VK_SUCCESS;
531 }
532 
533 static VkResult
nvk_image_plane_alloc_vma(struct nvk_device * dev,struct nvk_image_plane * plane,VkImageCreateFlags create_flags)534 nvk_image_plane_alloc_vma(struct nvk_device *dev,
535                           struct nvk_image_plane *plane,
536                           VkImageCreateFlags create_flags)
537 {
538    const bool sparse_bound =
539       create_flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT;
540    const bool sparse_resident =
541       create_flags & VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT;
542    assert(sparse_bound || !sparse_resident);
543 
544    if (sparse_bound || plane->nil.pte_kind) {
545       plane->vma_size_B = plane->nil.size_B;
546       plane->addr = nouveau_ws_alloc_vma(dev->ws_dev, 0, plane->vma_size_B,
547                                          plane->nil.align_B,
548                                          false, sparse_resident);
549       if (plane->addr == 0) {
550          return vk_errorf(dev, VK_ERROR_OUT_OF_DEVICE_MEMORY,
551                           "Sparse VMA allocation failed");
552       }
553    }
554 
555    return VK_SUCCESS;
556 }
557 
558 
559 static void
nvk_image_plane_finish(struct nvk_device * dev,struct nvk_image_plane * plane,VkImageCreateFlags create_flags,const VkAllocationCallbacks * pAllocator)560 nvk_image_plane_finish(struct nvk_device *dev,
561                        struct nvk_image_plane *plane,
562                        VkImageCreateFlags create_flags,
563                        const VkAllocationCallbacks *pAllocator)
564 {
565    if (plane->vma_size_B) {
566       const bool sparse_resident =
567          create_flags & VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT;
568 
569       nouveau_ws_bo_unbind_vma(dev->ws_dev, plane->addr, plane->vma_size_B);
570       nouveau_ws_free_vma(dev->ws_dev, plane->addr, plane->vma_size_B,
571                           false, sparse_resident);
572    }
573 }
574 
575 static void
nvk_image_finish(struct nvk_device * dev,struct nvk_image * image,const VkAllocationCallbacks * pAllocator)576 nvk_image_finish(struct nvk_device *dev, struct nvk_image *image,
577                  const VkAllocationCallbacks *pAllocator)
578 {
579    for (uint8_t plane = 0; plane < image->plane_count; plane++) {
580       nvk_image_plane_finish(dev, &image->planes[plane],
581                              image->vk.create_flags, pAllocator);
582    }
583 
584    if (image->stencil_copy_temp.nil.size_B > 0) {
585       nvk_image_plane_finish(dev, &image->stencil_copy_temp,
586                              image->vk.create_flags, pAllocator);
587    }
588 
589    vk_image_finish(&image->vk);
590 }
591 
592 VKAPI_ATTR VkResult VKAPI_CALL
nvk_CreateImage(VkDevice device,const VkImageCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkImage * pImage)593 nvk_CreateImage(VkDevice device,
594                 const VkImageCreateInfo *pCreateInfo,
595                 const VkAllocationCallbacks *pAllocator,
596                 VkImage *pImage)
597 {
598    VK_FROM_HANDLE(nvk_device, dev, device);
599    struct nvk_image *image;
600    VkResult result;
601 
602    image = vk_zalloc2(&dev->vk.alloc, pAllocator, sizeof(*image), 8,
603                       VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
604    if (!image)
605       return vk_error(dev, VK_ERROR_OUT_OF_HOST_MEMORY);
606 
607    result = nvk_image_init(dev, image, pCreateInfo);
608    if (result != VK_SUCCESS) {
609       vk_free2(&dev->vk.alloc, pAllocator, image);
610       return result;
611    }
612 
613    for (uint8_t plane = 0; plane < image->plane_count; plane++) {
614       result = nvk_image_plane_alloc_vma(dev, &image->planes[plane],
615                                          image->vk.create_flags);
616       if (result != VK_SUCCESS) {
617          nvk_image_finish(dev, image, pAllocator);
618          vk_free2(&dev->vk.alloc, pAllocator, image);
619          return result;
620       }
621    }
622 
623    if (image->stencil_copy_temp.nil.size_B > 0) {
624       result = nvk_image_plane_alloc_vma(dev, &image->stencil_copy_temp,
625                                          image->vk.create_flags);
626       if (result != VK_SUCCESS) {
627          nvk_image_finish(dev, image, pAllocator);
628          vk_free2(&dev->vk.alloc, pAllocator, image);
629          return result;
630       }
631    }
632 
633    *pImage = nvk_image_to_handle(image);
634 
635    return VK_SUCCESS;
636 }
637 
638 VKAPI_ATTR void VKAPI_CALL
nvk_DestroyImage(VkDevice device,VkImage _image,const VkAllocationCallbacks * pAllocator)639 nvk_DestroyImage(VkDevice device,
640                  VkImage _image,
641                  const VkAllocationCallbacks *pAllocator)
642 {
643    VK_FROM_HANDLE(nvk_device, dev, device);
644    VK_FROM_HANDLE(nvk_image, image, _image);
645 
646    if (!image)
647       return;
648 
649    nvk_image_finish(dev, image, pAllocator);
650    vk_free2(&dev->vk.alloc, pAllocator, image);
651 }
652 
653 static void
nvk_image_plane_add_req(struct nvk_image_plane * plane,uint64_t * size_B,uint32_t * align_B)654 nvk_image_plane_add_req(struct nvk_image_plane *plane,
655                         uint64_t *size_B, uint32_t *align_B)
656 {
657    assert(util_is_power_of_two_or_zero64(*align_B));
658    assert(util_is_power_of_two_or_zero64(plane->nil.align_B));
659 
660    *align_B = MAX2(*align_B, plane->nil.align_B);
661    *size_B = align64(*size_B, plane->nil.align_B);
662    *size_B += plane->nil.size_B;
663 }
664 
665 static void
nvk_get_image_memory_requirements(struct nvk_device * dev,struct nvk_image * image,VkImageAspectFlags aspects,VkMemoryRequirements2 * pMemoryRequirements)666 nvk_get_image_memory_requirements(struct nvk_device *dev,
667                                   struct nvk_image *image,
668                                   VkImageAspectFlags aspects,
669                                   VkMemoryRequirements2 *pMemoryRequirements)
670 {
671    uint32_t memory_types = (1 << dev->pdev->mem_type_count) - 1;
672 
673    // TODO hope for the best?
674 
675    uint64_t size_B = 0;
676    uint32_t align_B = 0;
677    if (image->disjoint) {
678       uint8_t plane = nvk_image_aspects_to_plane(image, aspects);
679       nvk_image_plane_add_req(&image->planes[plane], &size_B, &align_B);
680    } else {
681       for (unsigned plane = 0; plane < image->plane_count; plane++)
682          nvk_image_plane_add_req(&image->planes[plane], &size_B, &align_B);
683    }
684 
685    if (image->stencil_copy_temp.nil.size_B > 0)
686       nvk_image_plane_add_req(&image->stencil_copy_temp, &size_B, &align_B);
687 
688    pMemoryRequirements->memoryRequirements.memoryTypeBits = memory_types;
689    pMemoryRequirements->memoryRequirements.alignment = align_B;
690    pMemoryRequirements->memoryRequirements.size = size_B;
691 
692    vk_foreach_struct_const(ext, pMemoryRequirements->pNext) {
693       switch (ext->sType) {
694       case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: {
695          VkMemoryDedicatedRequirements *dedicated = (void *)ext;
696          dedicated->prefersDedicatedAllocation = false;
697          dedicated->requiresDedicatedAllocation = false;
698          break;
699       }
700       default:
701          nvk_debug_ignored_stype(ext->sType);
702          break;
703       }
704    }
705 }
706 
707 VKAPI_ATTR void VKAPI_CALL
nvk_GetImageMemoryRequirements2(VkDevice device,const VkImageMemoryRequirementsInfo2 * pInfo,VkMemoryRequirements2 * pMemoryRequirements)708 nvk_GetImageMemoryRequirements2(VkDevice device,
709                                 const VkImageMemoryRequirementsInfo2 *pInfo,
710                                 VkMemoryRequirements2 *pMemoryRequirements)
711 {
712    VK_FROM_HANDLE(nvk_device, dev, device);
713    VK_FROM_HANDLE(nvk_image, image, pInfo->image);
714 
715    const VkImagePlaneMemoryRequirementsInfo *plane_info =
716       vk_find_struct_const(pInfo->pNext, IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO);
717    const VkImageAspectFlags aspects =
718       image->disjoint ? plane_info->planeAspect : image->vk.aspects;
719 
720    nvk_get_image_memory_requirements(dev, image, aspects,
721                                      pMemoryRequirements);
722 }
723 
724 VKAPI_ATTR void VKAPI_CALL
nvk_GetDeviceImageMemoryRequirements(VkDevice device,const VkDeviceImageMemoryRequirements * pInfo,VkMemoryRequirements2 * pMemoryRequirements)725 nvk_GetDeviceImageMemoryRequirements(VkDevice device,
726                                      const VkDeviceImageMemoryRequirements *pInfo,
727                                      VkMemoryRequirements2 *pMemoryRequirements)
728 {
729    VK_FROM_HANDLE(nvk_device, dev, device);
730    ASSERTED VkResult result;
731    struct nvk_image image = {0};
732 
733    result = nvk_image_init(dev, &image, pInfo->pCreateInfo);
734    assert(result == VK_SUCCESS);
735 
736    const VkImageAspectFlags aspects =
737       image.disjoint ? pInfo->planeAspect : image.vk.aspects;
738 
739    nvk_get_image_memory_requirements(dev, &image, aspects,
740                                      pMemoryRequirements);
741 
742    nvk_image_finish(dev, &image, NULL);
743 }
744 
745 VKAPI_ATTR void VKAPI_CALL
nvk_GetImageSparseMemoryRequirements2(VkDevice device,const VkImageSparseMemoryRequirementsInfo2 * pInfo,uint32_t * pSparseMemoryRequirementCount,VkSparseImageMemoryRequirements2 * pSparseMemoryRequirements)746 nvk_GetImageSparseMemoryRequirements2(VkDevice device,
747                                       const VkImageSparseMemoryRequirementsInfo2* pInfo,
748                                       uint32_t* pSparseMemoryRequirementCount,
749                                       VkSparseImageMemoryRequirements2* pSparseMemoryRequirements)
750 {
751    /* We dont support sparse images yet, this is a stub to get KHR_get_memory_requirements2 */
752    *pSparseMemoryRequirementCount = 0;
753 }
754 
755 VKAPI_ATTR void VKAPI_CALL
nvk_GetDeviceImageSparseMemoryRequirements(VkDevice device,const VkDeviceImageMemoryRequirements * pInfo,uint32_t * pSparseMemoryRequirementCount,VkSparseImageMemoryRequirements2 * pSparseMemoryRequirements)756 nvk_GetDeviceImageSparseMemoryRequirements(VkDevice device,
757                                            const VkDeviceImageMemoryRequirements* pInfo,
758                                            uint32_t *pSparseMemoryRequirementCount,
759                                            VkSparseImageMemoryRequirements2 *pSparseMemoryRequirements)
760 {
761    /* Sparse images are not supported so this is just a stub for now. */
762    *pSparseMemoryRequirementCount = 0;
763 }
764 
765 static void
nvk_get_image_subresource_layout(UNUSED struct nvk_device * dev,struct nvk_image * image,const VkImageSubresource2KHR * pSubresource,VkSubresourceLayout2KHR * pLayout)766 nvk_get_image_subresource_layout(UNUSED struct nvk_device *dev,
767                                  struct nvk_image *image,
768                                  const VkImageSubresource2KHR *pSubresource,
769                                  VkSubresourceLayout2KHR *pLayout)
770 {
771    const VkImageSubresource *isr = &pSubresource->imageSubresource;
772 
773    const uint8_t p = nvk_image_aspects_to_plane(image, isr->aspectMask);
774    const struct nvk_image_plane *plane = &image->planes[p];
775 
776    uint64_t offset_B = 0;
777    if (!image->disjoint) {
778       uint32_t align_B = 0;
779       for (unsigned plane = 0; plane < p; plane++)
780          nvk_image_plane_add_req(&image->planes[plane], &offset_B, &align_B);
781    }
782    offset_B += nil_image_level_layer_offset_B(&plane->nil, isr->mipLevel,
783                                               isr->arrayLayer);
784 
785    pLayout->subresourceLayout = (VkSubresourceLayout) {
786       .offset = offset_B,
787       .size = nil_image_level_size_B(&plane->nil, isr->mipLevel),
788       .rowPitch = plane->nil.levels[isr->mipLevel].row_stride_B,
789       .arrayPitch = plane->nil.array_stride_B,
790       .depthPitch = nil_image_level_depth_stride_B(&plane->nil, isr->mipLevel),
791    };
792 }
793 
794 VKAPI_ATTR void VKAPI_CALL
nvk_GetImageSubresourceLayout2KHR(VkDevice device,VkImage _image,const VkImageSubresource2KHR * pSubresource,VkSubresourceLayout2KHR * pLayout)795 nvk_GetImageSubresourceLayout2KHR(VkDevice device,
796                                   VkImage _image,
797                                   const VkImageSubresource2KHR *pSubresource,
798                                   VkSubresourceLayout2KHR *pLayout)
799 {
800    VK_FROM_HANDLE(nvk_device, dev, device);
801    VK_FROM_HANDLE(nvk_image, image, _image);
802 
803    nvk_get_image_subresource_layout(dev, image, pSubresource, pLayout);
804 }
805 
806 VKAPI_ATTR void VKAPI_CALL
nvk_GetDeviceImageSubresourceLayoutKHR(VkDevice device,const VkDeviceImageSubresourceInfoKHR * pInfo,VkSubresourceLayout2KHR * pLayout)807 nvk_GetDeviceImageSubresourceLayoutKHR(
808     VkDevice device,
809     const VkDeviceImageSubresourceInfoKHR *pInfo,
810     VkSubresourceLayout2KHR *pLayout)
811 {
812    VK_FROM_HANDLE(nvk_device, dev, device);
813    ASSERTED VkResult result;
814    struct nvk_image image = {0};
815 
816    result = nvk_image_init(dev, &image, pInfo->pCreateInfo);
817    assert(result == VK_SUCCESS);
818 
819    nvk_get_image_subresource_layout(dev, &image, pInfo->pSubresource, pLayout);
820 
821    nvk_image_finish(dev, &image, NULL);
822 }
823 
824 static void
nvk_image_plane_bind(struct nvk_device * dev,struct nvk_image_plane * plane,struct nvk_device_memory * mem,uint64_t * offset_B)825 nvk_image_plane_bind(struct nvk_device *dev,
826                      struct nvk_image_plane *plane,
827                      struct nvk_device_memory *mem,
828                      uint64_t *offset_B)
829 {
830    *offset_B = align64(*offset_B, (uint64_t)plane->nil.align_B);
831 
832    if (plane->vma_size_B) {
833       nouveau_ws_bo_bind_vma(dev->ws_dev,
834                              mem->bo,
835                              plane->addr,
836                              plane->vma_size_B,
837                              *offset_B,
838                              plane->nil.pte_kind);
839    } else {
840       assert(plane->nil.pte_kind == 0);
841       plane->addr = mem->bo->offset + *offset_B;
842    }
843 
844    *offset_B += plane->nil.size_B;
845 }
846 
847 VKAPI_ATTR VkResult VKAPI_CALL
nvk_BindImageMemory2(VkDevice device,uint32_t bindInfoCount,const VkBindImageMemoryInfo * pBindInfos)848 nvk_BindImageMemory2(VkDevice device,
849                      uint32_t bindInfoCount,
850                      const VkBindImageMemoryInfo *pBindInfos)
851 {
852    VK_FROM_HANDLE(nvk_device, dev, device);
853    for (uint32_t i = 0; i < bindInfoCount; ++i) {
854       VK_FROM_HANDLE(nvk_device_memory, mem, pBindInfos[i].memory);
855       VK_FROM_HANDLE(nvk_image, image, pBindInfos[i].image);
856 
857       uint64_t offset_B = pBindInfos[i].memoryOffset;
858       if (image->disjoint) {
859          const VkBindImagePlaneMemoryInfo *plane_info =
860             vk_find_struct_const(pBindInfos[i].pNext, BIND_IMAGE_PLANE_MEMORY_INFO);
861          uint8_t plane = nvk_image_aspects_to_plane(image, plane_info->planeAspect);
862          nvk_image_plane_bind(dev, &image->planes[plane], mem, &offset_B);
863       } else {
864          for (unsigned plane = 0; plane < image->plane_count; plane++) {
865             nvk_image_plane_bind(dev, &image->planes[plane], mem, &offset_B);
866          }
867       }
868 
869       if (image->stencil_copy_temp.nil.size_B > 0)
870          nvk_image_plane_bind(dev, &image->stencil_copy_temp, mem, &offset_B);
871    }
872 
873    return VK_SUCCESS;
874 }
875