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