1 /*
2 * Copyright © 2015 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 #include <assert.h>
25 #include <stdbool.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29 #include <sys/mman.h>
30 #include "drm-uapi/drm_fourcc.h"
31
32 #include "anv_private.h"
33 #include "util/debug.h"
34 #include "vk_util.h"
35 #include "util/u_math.h"
36
37 #include "vk_format.h"
38
39 #define ANV_OFFSET_IMPLICIT UINT64_MAX
40
41 static const enum isl_surf_dim
42 vk_to_isl_surf_dim[] = {
43 [VK_IMAGE_TYPE_1D] = ISL_SURF_DIM_1D,
44 [VK_IMAGE_TYPE_2D] = ISL_SURF_DIM_2D,
45 [VK_IMAGE_TYPE_3D] = ISL_SURF_DIM_3D,
46 };
47
48 static uint64_t MUST_CHECK UNUSED
memory_range_end(struct anv_image_memory_range memory_range)49 memory_range_end(struct anv_image_memory_range memory_range)
50 {
51 assert(anv_is_aligned(memory_range.offset, memory_range.alignment));
52 return memory_range.offset + memory_range.size;
53 }
54
55 /**
56 * Get binding for VkImagePlaneMemoryRequirementsInfo,
57 * VkBindImagePlaneMemoryInfo and VkDeviceImageMemoryRequirementsKHR.
58 */
59 static struct anv_image_binding *
image_aspect_to_binding(struct anv_image * image,VkImageAspectFlags aspect)60 image_aspect_to_binding(struct anv_image *image, VkImageAspectFlags aspect)
61 {
62 uint32_t plane;
63
64 assert(image->disjoint);
65
66 if (image->vk.tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) {
67 /* Spec requires special aspects for modifier images. */
68 assert(aspect >= VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT &&
69 aspect <= VK_IMAGE_ASPECT_MEMORY_PLANE_3_BIT_EXT);
70
71 /* We don't advertise DISJOINT for modifiers with aux, and therefore we
72 * don't handle queries of the modifier's "aux plane" here.
73 */
74 assert(!isl_drm_modifier_has_aux(image->vk.drm_format_mod));
75
76 plane = aspect - VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT;
77 } else {
78 plane = anv_image_aspect_to_plane(image, aspect);
79 }
80
81 return &image->bindings[ANV_IMAGE_MEMORY_BINDING_PLANE_0 + plane];
82 }
83
84 /**
85 * Extend the memory binding's range by appending a new memory range with `size`
86 * and `alignment` at `offset`. Return the appended range.
87 *
88 * Offset is ignored if ANV_OFFSET_IMPLICIT.
89 *
90 * The given binding must not be ANV_IMAGE_MEMORY_BINDING_MAIN. The function
91 * converts to MAIN as needed.
92 */
93 static VkResult MUST_CHECK
image_binding_grow(const struct anv_device * device,struct anv_image * image,enum anv_image_memory_binding binding,uint64_t offset,uint64_t size,uint32_t alignment,struct anv_image_memory_range * out_range)94 image_binding_grow(const struct anv_device *device,
95 struct anv_image *image,
96 enum anv_image_memory_binding binding,
97 uint64_t offset,
98 uint64_t size,
99 uint32_t alignment,
100 struct anv_image_memory_range *out_range)
101 {
102 /* We overwrite 'offset' but need to remember if it was implicit. */
103 const bool has_implicit_offset = (offset == ANV_OFFSET_IMPLICIT);
104
105 assert(size > 0);
106 assert(util_is_power_of_two_or_zero(alignment));
107
108 switch (binding) {
109 case ANV_IMAGE_MEMORY_BINDING_MAIN:
110 /* The caller must not pre-translate BINDING_PLANE_i to BINDING_MAIN. */
111 unreachable("ANV_IMAGE_MEMORY_BINDING_MAIN");
112 case ANV_IMAGE_MEMORY_BINDING_PLANE_0:
113 case ANV_IMAGE_MEMORY_BINDING_PLANE_1:
114 case ANV_IMAGE_MEMORY_BINDING_PLANE_2:
115 if (!image->disjoint)
116 binding = ANV_IMAGE_MEMORY_BINDING_MAIN;
117 break;
118 case ANV_IMAGE_MEMORY_BINDING_PRIVATE:
119 assert(offset == ANV_OFFSET_IMPLICIT);
120 break;
121 case ANV_IMAGE_MEMORY_BINDING_END:
122 unreachable("ANV_IMAGE_MEMORY_BINDING_END");
123 }
124
125 struct anv_image_memory_range *container =
126 &image->bindings[binding].memory_range;
127
128 if (has_implicit_offset) {
129 offset = align_u64(container->offset + container->size, alignment);
130 } else {
131 /* Offset must be validated because it comes from
132 * VkImageDrmFormatModifierExplicitCreateInfoEXT.
133 */
134 if (unlikely(!anv_is_aligned(offset, alignment))) {
135 return vk_errorf(device,
136 VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT,
137 "VkImageDrmFormatModifierExplicitCreateInfoEXT::"
138 "pPlaneLayouts[]::offset is misaligned");
139 }
140
141 /* We require that surfaces be added in memory-order. This simplifies the
142 * layout validation required by
143 * VkImageDrmFormatModifierExplicitCreateInfoEXT,
144 */
145 if (unlikely(offset < container->size)) {
146 return vk_errorf(device,
147 VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT,
148 "VkImageDrmFormatModifierExplicitCreateInfoEXT::"
149 "pPlaneLayouts[]::offset is too small");
150 }
151 }
152
153 if (__builtin_add_overflow(offset, size, &container->size)) {
154 if (has_implicit_offset) {
155 assert(!"overflow");
156 return vk_errorf(device, VK_ERROR_UNKNOWN,
157 "internal error: overflow in %s", __func__);
158 } else {
159 return vk_errorf(device,
160 VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT,
161 "VkImageDrmFormatModifierExplicitCreateInfoEXT::"
162 "pPlaneLayouts[]::offset is too large");
163 }
164 }
165
166 container->alignment = MAX2(container->alignment, alignment);
167
168 *out_range = (struct anv_image_memory_range) {
169 .binding = binding,
170 .offset = offset,
171 .size = size,
172 .alignment = alignment,
173 };
174
175 return VK_SUCCESS;
176 }
177
178 /**
179 * Adjust range 'a' to contain range 'b'.
180 *
181 * For simplicity's sake, the offset of 'a' must be 0 and remains 0.
182 * If 'a' and 'b' target different bindings, then no merge occurs.
183 */
184 static void
memory_range_merge(struct anv_image_memory_range * a,const struct anv_image_memory_range b)185 memory_range_merge(struct anv_image_memory_range *a,
186 const struct anv_image_memory_range b)
187 {
188 if (b.size == 0)
189 return;
190
191 if (a->binding != b.binding)
192 return;
193
194 assert(a->offset == 0);
195 assert(anv_is_aligned(a->offset, a->alignment));
196 assert(anv_is_aligned(b.offset, b.alignment));
197
198 a->alignment = MAX2(a->alignment, b.alignment);
199 a->size = MAX2(a->size, b.offset + b.size);
200 }
201
202 static isl_surf_usage_flags_t
choose_isl_surf_usage(VkImageCreateFlags vk_create_flags,VkImageUsageFlags vk_usage,isl_surf_usage_flags_t isl_extra_usage,VkImageAspectFlagBits aspect)203 choose_isl_surf_usage(VkImageCreateFlags vk_create_flags,
204 VkImageUsageFlags vk_usage,
205 isl_surf_usage_flags_t isl_extra_usage,
206 VkImageAspectFlagBits aspect)
207 {
208 isl_surf_usage_flags_t isl_usage = isl_extra_usage;
209
210 if (vk_usage & VK_IMAGE_USAGE_SAMPLED_BIT)
211 isl_usage |= ISL_SURF_USAGE_TEXTURE_BIT;
212
213 if (vk_usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)
214 isl_usage |= ISL_SURF_USAGE_TEXTURE_BIT;
215
216 if (vk_usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
217 isl_usage |= ISL_SURF_USAGE_RENDER_TARGET_BIT;
218
219 if (vk_create_flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT)
220 isl_usage |= ISL_SURF_USAGE_CUBE_BIT;
221
222 /* Even if we're only using it for transfer operations, clears to depth and
223 * stencil images happen as depth and stencil so they need the right ISL
224 * usage bits or else things will fall apart.
225 */
226 switch (aspect) {
227 case VK_IMAGE_ASPECT_DEPTH_BIT:
228 isl_usage |= ISL_SURF_USAGE_DEPTH_BIT;
229 break;
230 case VK_IMAGE_ASPECT_STENCIL_BIT:
231 isl_usage |= ISL_SURF_USAGE_STENCIL_BIT;
232 break;
233 case VK_IMAGE_ASPECT_COLOR_BIT:
234 case VK_IMAGE_ASPECT_PLANE_0_BIT:
235 case VK_IMAGE_ASPECT_PLANE_1_BIT:
236 case VK_IMAGE_ASPECT_PLANE_2_BIT:
237 break;
238 default:
239 unreachable("bad VkImageAspect");
240 }
241
242 if (vk_usage & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) {
243 /* blorp implements transfers by sampling from the source image. */
244 isl_usage |= ISL_SURF_USAGE_TEXTURE_BIT;
245 }
246
247 if (vk_usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT &&
248 aspect == VK_IMAGE_ASPECT_COLOR_BIT) {
249 /* blorp implements transfers by rendering into the destination image.
250 * Only request this with color images, as we deal with depth/stencil
251 * formats differently. */
252 isl_usage |= ISL_SURF_USAGE_RENDER_TARGET_BIT;
253 }
254
255 return isl_usage;
256 }
257
258 static isl_tiling_flags_t
choose_isl_tiling_flags(const struct intel_device_info * devinfo,const struct anv_image_create_info * anv_info,const struct isl_drm_modifier_info * isl_mod_info,bool legacy_scanout)259 choose_isl_tiling_flags(const struct intel_device_info *devinfo,
260 const struct anv_image_create_info *anv_info,
261 const struct isl_drm_modifier_info *isl_mod_info,
262 bool legacy_scanout)
263 {
264 const VkImageCreateInfo *base_info = anv_info->vk_info;
265 isl_tiling_flags_t flags = 0;
266
267 assert((isl_mod_info != NULL) ==
268 (base_info->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT));
269
270 switch (base_info->tiling) {
271 default:
272 unreachable("bad VkImageTiling");
273 case VK_IMAGE_TILING_OPTIMAL:
274 flags = ISL_TILING_ANY_MASK;
275 break;
276 case VK_IMAGE_TILING_LINEAR:
277 flags = ISL_TILING_LINEAR_BIT;
278 break;
279 case VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT:
280 flags = 1 << isl_mod_info->tiling;
281 }
282
283 if (anv_info->isl_tiling_flags) {
284 assert(isl_mod_info == NULL);
285 flags &= anv_info->isl_tiling_flags;
286 }
287
288 if (legacy_scanout) {
289 isl_tiling_flags_t legacy_mask = ISL_TILING_LINEAR_BIT;
290 if (devinfo->has_tiling_uapi)
291 legacy_mask |= ISL_TILING_X_BIT;
292 flags &= legacy_mask;
293 }
294
295 assert(flags);
296
297 return flags;
298 }
299
300 /**
301 * Add the surface to the binding at the given offset.
302 *
303 * \see image_binding_grow()
304 */
305 static VkResult MUST_CHECK
add_surface(struct anv_device * device,struct anv_image * image,struct anv_surface * surf,enum anv_image_memory_binding binding,uint64_t offset)306 add_surface(struct anv_device *device,
307 struct anv_image *image,
308 struct anv_surface *surf,
309 enum anv_image_memory_binding binding,
310 uint64_t offset)
311 {
312 /* isl surface must be initialized */
313 assert(surf->isl.size_B > 0);
314
315 return image_binding_grow(device, image, binding, offset,
316 surf->isl.size_B,
317 surf->isl.alignment_B,
318 &surf->memory_range);
319 }
320
321 /**
322 * Do hardware limitations require the image plane to use a shadow surface?
323 *
324 * If hardware limitations force us to use a shadow surface, then the same
325 * limitations may also constrain the tiling of the primary surface; therefore
326 * paramater @a inout_primary_tiling_flags.
327 *
328 * If the image plane is a separate stencil plane and if the user provided
329 * VkImageStencilUsageCreateInfoEXT, then @a usage must be stencilUsage.
330 *
331 * @see anv_image::planes[]::shadow_surface
332 */
333 static bool
anv_image_plane_needs_shadow_surface(const struct intel_device_info * devinfo,struct anv_format_plane plane_format,VkImageTiling vk_tiling,VkImageUsageFlags vk_plane_usage,VkImageCreateFlags vk_create_flags,isl_tiling_flags_t * inout_primary_tiling_flags)334 anv_image_plane_needs_shadow_surface(const struct intel_device_info *devinfo,
335 struct anv_format_plane plane_format,
336 VkImageTiling vk_tiling,
337 VkImageUsageFlags vk_plane_usage,
338 VkImageCreateFlags vk_create_flags,
339 isl_tiling_flags_t *inout_primary_tiling_flags)
340 {
341 if (devinfo->ver <= 8 &&
342 (vk_create_flags & VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT) &&
343 vk_tiling == VK_IMAGE_TILING_OPTIMAL) {
344 /* We must fallback to a linear surface because we may not be able to
345 * correctly handle the offsets if tiled. (On gfx9,
346 * RENDER_SURFACE_STATE::X/Y Offset are sufficient). To prevent garbage
347 * performance while texturing, we maintain a tiled shadow surface.
348 */
349 assert(isl_format_is_compressed(plane_format.isl_format));
350
351 if (inout_primary_tiling_flags) {
352 *inout_primary_tiling_flags = ISL_TILING_LINEAR_BIT;
353 }
354
355 return true;
356 }
357
358 if (devinfo->ver <= 7 &&
359 plane_format.aspect == VK_IMAGE_ASPECT_STENCIL_BIT &&
360 (vk_plane_usage & VK_IMAGE_USAGE_SAMPLED_BIT)) {
361 /* gfx7 can't sample from W-tiled surfaces. */
362 return true;
363 }
364
365 return false;
366 }
367
368 bool
anv_formats_ccs_e_compatible(const struct intel_device_info * devinfo,VkImageCreateFlags create_flags,VkFormat vk_format,VkImageTiling vk_tiling,const VkImageFormatListCreateInfoKHR * fmt_list)369 anv_formats_ccs_e_compatible(const struct intel_device_info *devinfo,
370 VkImageCreateFlags create_flags,
371 VkFormat vk_format,
372 VkImageTiling vk_tiling,
373 const VkImageFormatListCreateInfoKHR *fmt_list)
374 {
375 enum isl_format format =
376 anv_get_isl_format(devinfo, vk_format,
377 VK_IMAGE_ASPECT_COLOR_BIT, vk_tiling);
378
379 if (!isl_format_supports_ccs_e(devinfo, format))
380 return false;
381
382 if (!(create_flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT))
383 return true;
384
385 if (!fmt_list || fmt_list->viewFormatCount == 0)
386 return false;
387
388 for (uint32_t i = 0; i < fmt_list->viewFormatCount; i++) {
389 enum isl_format view_format =
390 anv_get_isl_format(devinfo, fmt_list->pViewFormats[i],
391 VK_IMAGE_ASPECT_COLOR_BIT, vk_tiling);
392
393 if (!isl_formats_are_ccs_e_compatible(devinfo, format, view_format))
394 return false;
395 }
396
397 return true;
398 }
399
400 /**
401 * For color images that have an auxiliary surface, request allocation for an
402 * additional buffer that mainly stores fast-clear values. Use of this buffer
403 * allows us to access the image's subresources while being aware of their
404 * fast-clear values in non-trivial cases (e.g., outside of a render pass in
405 * which a fast clear has occurred).
406 *
407 * In order to avoid having multiple clear colors for a single plane of an
408 * image (hence a single RENDER_SURFACE_STATE), we only allow fast-clears on
409 * the first slice (level 0, layer 0). At the time of our testing (Jan 17,
410 * 2018), there were no known applications which would benefit from fast-
411 * clearing more than just the first slice.
412 *
413 * The fast clear portion of the image is laid out in the following order:
414 *
415 * * 1 or 4 dwords (depending on hardware generation) for the clear color
416 * * 1 dword for the anv_fast_clear_type of the clear color
417 * * On gfx9+, 1 dword per level and layer of the image (3D levels count
418 * multiple layers) in level-major order for compression state.
419 *
420 * For the purpose of discoverability, the algorithm used to manage
421 * compression and fast-clears is described here:
422 *
423 * * On a transition from UNDEFINED or PREINITIALIZED to a defined layout,
424 * all of the values in the fast clear portion of the image are initialized
425 * to default values.
426 *
427 * * On fast-clear, the clear value is written into surface state and also
428 * into the buffer and the fast clear type is set appropriately. Both
429 * setting the fast-clear value in the buffer and setting the fast-clear
430 * type happen from the GPU using MI commands.
431 *
432 * * Whenever a render or blorp operation is performed with CCS_E, we call
433 * genX(cmd_buffer_mark_image_written) to set the compression state to
434 * true (which is represented by UINT32_MAX).
435 *
436 * * On pipeline barrier transitions, the worst-case transition is computed
437 * from the image layouts. The command streamer inspects the fast clear
438 * type and compression state dwords and constructs a predicate. The
439 * worst-case resolve is performed with the given predicate and the fast
440 * clear and compression state is set accordingly.
441 *
442 * See anv_layout_to_aux_usage and anv_layout_to_fast_clear_type functions for
443 * details on exactly what is allowed in what layouts.
444 *
445 * On gfx7-9, we do not have a concept of indirect clear colors in hardware.
446 * In order to deal with this, we have to do some clear color management.
447 *
448 * * For LOAD_OP_LOAD at the top of a renderpass, we have to copy the clear
449 * value from the buffer into the surface state with MI commands.
450 *
451 * * For any blorp operations, we pass the address to the clear value into
452 * blorp and it knows to copy the clear color.
453 */
454 static VkResult MUST_CHECK
add_aux_state_tracking_buffer(struct anv_device * device,struct anv_image * image,uint32_t plane)455 add_aux_state_tracking_buffer(struct anv_device *device,
456 struct anv_image *image,
457 uint32_t plane)
458 {
459 assert(image && device);
460 assert(image->planes[plane].aux_usage != ISL_AUX_USAGE_NONE &&
461 image->vk.aspects & (VK_IMAGE_ASPECT_ANY_COLOR_BIT_ANV |
462 VK_IMAGE_ASPECT_DEPTH_BIT));
463
464 const unsigned clear_color_state_size = device->info.ver >= 10 ?
465 device->isl_dev.ss.clear_color_state_size :
466 device->isl_dev.ss.clear_value_size;
467
468 /* Clear color and fast clear type */
469 unsigned state_size = clear_color_state_size + 4;
470
471 /* We only need to track compression on CCS_E surfaces. */
472 if (image->planes[plane].aux_usage == ISL_AUX_USAGE_CCS_E) {
473 if (image->vk.image_type == VK_IMAGE_TYPE_3D) {
474 for (uint32_t l = 0; l < image->vk.mip_levels; l++)
475 state_size += anv_minify(image->vk.extent.depth, l) * 4;
476 } else {
477 state_size += image->vk.mip_levels * image->vk.array_layers * 4;
478 }
479 }
480
481 enum anv_image_memory_binding binding =
482 ANV_IMAGE_MEMORY_BINDING_PLANE_0 + plane;
483
484 if (image->vk.drm_format_mod != DRM_FORMAT_MOD_INVALID)
485 binding = ANV_IMAGE_MEMORY_BINDING_PRIVATE;
486
487 /* We believe that 256B alignment may be sufficient, but we choose 4K due to
488 * lack of testing. And MI_LOAD/STORE operations require dword-alignment.
489 */
490 return image_binding_grow(device, image, binding,
491 ANV_OFFSET_IMPLICIT, state_size, 4096,
492 &image->planes[plane].fast_clear_memory_range);
493 }
494
495 /**
496 * The return code indicates whether creation of the VkImage should continue
497 * or fail, not whether the creation of the aux surface succeeded. If the aux
498 * surface is not required (for example, by neither hardware nor DRM format
499 * modifier), then this may return VK_SUCCESS when creation of the aux surface
500 * fails.
501 *
502 * @param offset See add_surface()
503 */
504 static VkResult
add_aux_surface_if_supported(struct anv_device * device,struct anv_image * image,uint32_t plane,struct anv_format_plane plane_format,const VkImageFormatListCreateInfoKHR * fmt_list,uint64_t offset,uint32_t stride,isl_surf_usage_flags_t isl_extra_usage_flags)505 add_aux_surface_if_supported(struct anv_device *device,
506 struct anv_image *image,
507 uint32_t plane,
508 struct anv_format_plane plane_format,
509 const VkImageFormatListCreateInfoKHR *fmt_list,
510 uint64_t offset,
511 uint32_t stride,
512 isl_surf_usage_flags_t isl_extra_usage_flags)
513 {
514 VkImageAspectFlags aspect = plane_format.aspect;
515 VkResult result;
516 bool ok;
517
518 /* The aux surface must not be already added. */
519 assert(!anv_surface_is_valid(&image->planes[plane].aux_surface));
520
521 if ((isl_extra_usage_flags & ISL_SURF_USAGE_DISABLE_AUX_BIT))
522 return VK_SUCCESS;
523
524 if (aspect == VK_IMAGE_ASPECT_DEPTH_BIT) {
525 /* We don't advertise that depth buffers could be used as storage
526 * images.
527 */
528 assert(!(image->vk.usage & VK_IMAGE_USAGE_STORAGE_BIT));
529
530 /* Allow the user to control HiZ enabling. Disable by default on gfx7
531 * because resolves are not currently implemented pre-BDW.
532 */
533 if (!(image->vk.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) {
534 /* It will never be used as an attachment, HiZ is pointless. */
535 return VK_SUCCESS;
536 }
537
538 if (device->info.ver == 7) {
539 anv_perf_warn(VK_LOG_OBJS(&image->vk.base), "Implement gfx7 HiZ");
540 return VK_SUCCESS;
541 }
542
543 if (image->vk.mip_levels > 1) {
544 anv_perf_warn(VK_LOG_OBJS(&image->vk.base), "Enable multi-LOD HiZ");
545 return VK_SUCCESS;
546 }
547
548 if (device->info.ver == 8 && image->vk.samples > 1) {
549 anv_perf_warn(VK_LOG_OBJS(&image->vk.base),
550 "Enable gfx8 multisampled HiZ");
551 return VK_SUCCESS;
552 }
553
554 if (INTEL_DEBUG(DEBUG_NO_HIZ))
555 return VK_SUCCESS;
556
557 ok = isl_surf_get_hiz_surf(&device->isl_dev,
558 &image->planes[plane].primary_surface.isl,
559 &image->planes[plane].aux_surface.isl);
560 if (!ok)
561 return VK_SUCCESS;
562
563 if (!isl_surf_supports_ccs(&device->isl_dev,
564 &image->planes[plane].primary_surface.isl,
565 &image->planes[plane].aux_surface.isl)) {
566 image->planes[plane].aux_usage = ISL_AUX_USAGE_HIZ;
567 } else if (image->vk.usage & (VK_IMAGE_USAGE_SAMPLED_BIT |
568 VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) &&
569 image->vk.samples == 1) {
570 /* If it's used as an input attachment or a texture and it's
571 * single-sampled (this is a requirement for HiZ+CCS write-through
572 * mode), use write-through mode so that we don't need to resolve
573 * before texturing. This will make depth testing a bit slower but
574 * texturing faster.
575 *
576 * TODO: This is a heuristic trade-off; we haven't tuned it at all.
577 */
578 assert(device->info.ver >= 12);
579 image->planes[plane].aux_usage = ISL_AUX_USAGE_HIZ_CCS_WT;
580 } else {
581 assert(device->info.ver >= 12);
582 image->planes[plane].aux_usage = ISL_AUX_USAGE_HIZ_CCS;
583 }
584
585 result = add_surface(device, image, &image->planes[plane].aux_surface,
586 ANV_IMAGE_MEMORY_BINDING_PLANE_0 + plane,
587 ANV_OFFSET_IMPLICIT);
588 if (result != VK_SUCCESS)
589 return result;
590
591 if (image->planes[plane].aux_usage == ISL_AUX_USAGE_HIZ_CCS_WT)
592 return add_aux_state_tracking_buffer(device, image, plane);
593 } else if (aspect == VK_IMAGE_ASPECT_STENCIL_BIT) {
594
595 if (INTEL_DEBUG(DEBUG_NO_RBC))
596 return VK_SUCCESS;
597
598 if (!isl_surf_supports_ccs(&device->isl_dev,
599 &image->planes[plane].primary_surface.isl,
600 NULL))
601 return VK_SUCCESS;
602
603 image->planes[plane].aux_usage = ISL_AUX_USAGE_STC_CCS;
604 } else if ((aspect & VK_IMAGE_ASPECT_ANY_COLOR_BIT_ANV) && image->vk.samples == 1) {
605 if (image->n_planes != 1) {
606 /* Multiplanar images seem to hit a sampler bug with CCS and R16G16
607 * format. (Putting the clear state a page/4096bytes further fixes
608 * the issue).
609 */
610 return VK_SUCCESS;
611 }
612
613 if ((image->vk.create_flags & VK_IMAGE_CREATE_ALIAS_BIT)) {
614 /* The image may alias a plane of a multiplanar image. Above we ban
615 * CCS on multiplanar images.
616 *
617 * We must also reject aliasing of any image that uses
618 * ANV_IMAGE_MEMORY_BINDING_PRIVATE. Since we're already rejecting all
619 * aliasing here, there's no need to further analyze if the image needs
620 * a private binding.
621 */
622 return VK_SUCCESS;
623 }
624
625 if (!isl_format_supports_rendering(&device->info,
626 plane_format.isl_format)) {
627 /* Disable CCS because it is not useful (we can't render to the image
628 * with CCS enabled). While it may be technically possible to enable
629 * CCS for this case, we currently don't have things hooked up to get
630 * it working.
631 */
632 anv_perf_warn(VK_LOG_OBJS(&image->vk.base),
633 "This image format doesn't support rendering. "
634 "Not allocating an CCS buffer.");
635 return VK_SUCCESS;
636 }
637
638 if (INTEL_DEBUG(DEBUG_NO_RBC))
639 return VK_SUCCESS;
640
641 ok = isl_surf_get_ccs_surf(&device->isl_dev,
642 &image->planes[plane].primary_surface.isl,
643 NULL,
644 &image->planes[plane].aux_surface.isl,
645 stride);
646 if (!ok)
647 return VK_SUCCESS;
648
649 /* Choose aux usage */
650 if (!(image->vk.usage & VK_IMAGE_USAGE_STORAGE_BIT) &&
651 anv_formats_ccs_e_compatible(&device->info,
652 image->vk.create_flags,
653 image->vk.format,
654 image->vk.tiling,
655 fmt_list)) {
656 /* For images created without MUTABLE_FORMAT_BIT set, we know that
657 * they will always be used with the original format. In particular,
658 * they will always be used with a format that supports color
659 * compression. If it's never used as a storage image, then it will
660 * only be used through the sampler or the as a render target. This
661 * means that it's safe to just leave compression on at all times for
662 * these formats.
663 */
664 image->planes[plane].aux_usage = ISL_AUX_USAGE_CCS_E;
665 } else if (device->info.ver >= 12) {
666 anv_perf_warn(VK_LOG_OBJS(&image->vk.base),
667 "The CCS_D aux mode is not yet handled on "
668 "Gfx12+. Not allocating a CCS buffer.");
669 image->planes[plane].aux_surface.isl.size_B = 0;
670 return VK_SUCCESS;
671 } else {
672 image->planes[plane].aux_usage = ISL_AUX_USAGE_CCS_D;
673 }
674
675 if (!device->physical->has_implicit_ccs) {
676 enum anv_image_memory_binding binding =
677 ANV_IMAGE_MEMORY_BINDING_PLANE_0 + plane;
678
679 if (image->vk.drm_format_mod != DRM_FORMAT_MOD_INVALID &&
680 !isl_drm_modifier_has_aux(image->vk.drm_format_mod))
681 binding = ANV_IMAGE_MEMORY_BINDING_PRIVATE;
682
683 result = add_surface(device, image, &image->planes[plane].aux_surface,
684 binding, offset);
685 if (result != VK_SUCCESS)
686 return result;
687 }
688
689 return add_aux_state_tracking_buffer(device, image, plane);
690 } else if ((aspect & VK_IMAGE_ASPECT_ANY_COLOR_BIT_ANV) && image->vk.samples > 1) {
691 assert(!(image->vk.usage & VK_IMAGE_USAGE_STORAGE_BIT));
692 ok = isl_surf_get_mcs_surf(&device->isl_dev,
693 &image->planes[plane].primary_surface.isl,
694 &image->planes[plane].aux_surface.isl);
695 if (!ok)
696 return VK_SUCCESS;
697
698 image->planes[plane].aux_usage = ISL_AUX_USAGE_MCS;
699
700 result = add_surface(device, image, &image->planes[plane].aux_surface,
701 ANV_IMAGE_MEMORY_BINDING_PLANE_0 + plane,
702 ANV_OFFSET_IMPLICIT);
703 if (result != VK_SUCCESS)
704 return result;
705
706 return add_aux_state_tracking_buffer(device, image, plane);
707 }
708
709 return VK_SUCCESS;
710 }
711
712 static VkResult
add_shadow_surface(struct anv_device * device,struct anv_image * image,uint32_t plane,struct anv_format_plane plane_format,uint32_t stride,VkImageUsageFlags vk_plane_usage)713 add_shadow_surface(struct anv_device *device,
714 struct anv_image *image,
715 uint32_t plane,
716 struct anv_format_plane plane_format,
717 uint32_t stride,
718 VkImageUsageFlags vk_plane_usage)
719 {
720 ASSERTED bool ok;
721
722 ok = isl_surf_init(&device->isl_dev,
723 &image->planes[plane].shadow_surface.isl,
724 .dim = vk_to_isl_surf_dim[image->vk.image_type],
725 .format = plane_format.isl_format,
726 .width = image->vk.extent.width,
727 .height = image->vk.extent.height,
728 .depth = image->vk.extent.depth,
729 .levels = image->vk.mip_levels,
730 .array_len = image->vk.array_layers,
731 .samples = image->vk.samples,
732 .min_alignment_B = 0,
733 .row_pitch_B = stride,
734 .usage = ISL_SURF_USAGE_TEXTURE_BIT |
735 (vk_plane_usage & ISL_SURF_USAGE_CUBE_BIT),
736 .tiling_flags = ISL_TILING_ANY_MASK);
737
738 /* isl_surf_init() will fail only if provided invalid input. Invalid input
739 * here is illegal in Vulkan.
740 */
741 assert(ok);
742
743 return add_surface(device, image, &image->planes[plane].shadow_surface,
744 ANV_IMAGE_MEMORY_BINDING_PLANE_0 + plane,
745 ANV_OFFSET_IMPLICIT);
746 }
747
748 /**
749 * Initialize the anv_image::*_surface selected by \a aspect. Then update the
750 * image's memory requirements (that is, the image's size and alignment).
751 *
752 * @param offset See add_surface()
753 */
754 static VkResult
add_primary_surface(struct anv_device * device,struct anv_image * image,uint32_t plane,struct anv_format_plane plane_format,uint64_t offset,uint32_t stride,isl_tiling_flags_t isl_tiling_flags,isl_surf_usage_flags_t isl_usage)755 add_primary_surface(struct anv_device *device,
756 struct anv_image *image,
757 uint32_t plane,
758 struct anv_format_plane plane_format,
759 uint64_t offset,
760 uint32_t stride,
761 isl_tiling_flags_t isl_tiling_flags,
762 isl_surf_usage_flags_t isl_usage)
763 {
764 struct anv_surface *anv_surf = &image->planes[plane].primary_surface;
765 bool ok;
766
767 ok = isl_surf_init(&device->isl_dev, &anv_surf->isl,
768 .dim = vk_to_isl_surf_dim[image->vk.image_type],
769 .format = plane_format.isl_format,
770 .width = image->vk.extent.width / plane_format.denominator_scales[0],
771 .height = image->vk.extent.height / plane_format.denominator_scales[1],
772 .depth = image->vk.extent.depth,
773 .levels = image->vk.mip_levels,
774 .array_len = image->vk.array_layers,
775 .samples = image->vk.samples,
776 .min_alignment_B = 0,
777 .row_pitch_B = stride,
778 .usage = isl_usage,
779 .tiling_flags = isl_tiling_flags);
780
781 if (!ok) {
782 /* TODO: Should return
783 * VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT in come cases.
784 */
785 return VK_ERROR_OUT_OF_DEVICE_MEMORY;
786 }
787
788 image->planes[plane].aux_usage = ISL_AUX_USAGE_NONE;
789
790 return add_surface(device, image, anv_surf,
791 ANV_IMAGE_MEMORY_BINDING_PLANE_0 + plane, offset);
792 }
793
794 #ifndef NDEBUG
795 static bool MUST_CHECK
memory_range_is_aligned(struct anv_image_memory_range memory_range)796 memory_range_is_aligned(struct anv_image_memory_range memory_range)
797 {
798 return anv_is_aligned(memory_range.offset, memory_range.alignment);
799 }
800 #endif
801
802 struct check_memory_range_params {
803 struct anv_image_memory_range *accum_ranges;
804 const struct anv_surface *test_surface;
805 const struct anv_image_memory_range *test_range;
806 enum anv_image_memory_binding expect_binding;
807 };
808
809 #define check_memory_range(...) \
810 check_memory_range_s(&(struct check_memory_range_params) { __VA_ARGS__ })
811
812 static void UNUSED
check_memory_range_s(const struct check_memory_range_params * p)813 check_memory_range_s(const struct check_memory_range_params *p)
814 {
815 assert((p->test_surface == NULL) != (p->test_range == NULL));
816
817 const struct anv_image_memory_range *test_range =
818 p->test_range ?: &p->test_surface->memory_range;
819
820 struct anv_image_memory_range *accum_range =
821 &p->accum_ranges[p->expect_binding];
822
823 assert(test_range->binding == p->expect_binding);
824 assert(test_range->offset >= memory_range_end(*accum_range));
825 assert(memory_range_is_aligned(*test_range));
826
827 if (p->test_surface) {
828 assert(anv_surface_is_valid(p->test_surface));
829 assert(p->test_surface->memory_range.alignment ==
830 p->test_surface->isl.alignment_B);
831 }
832
833 memory_range_merge(accum_range, *test_range);
834 }
835
836 /**
837 * Validate the image's memory bindings *after* all its surfaces and memory
838 * ranges are final.
839 *
840 * For simplicity's sake, we do not validate free-form layout of the image's
841 * memory bindings. We validate the layout described in the comments of struct
842 * anv_image.
843 */
844 static void
check_memory_bindings(const struct anv_device * device,const struct anv_image * image)845 check_memory_bindings(const struct anv_device *device,
846 const struct anv_image *image)
847 {
848 #ifdef DEBUG
849 /* As we inspect each part of the image, we merge the part's memory range
850 * into these accumulation ranges.
851 */
852 struct anv_image_memory_range accum_ranges[ANV_IMAGE_MEMORY_BINDING_END];
853 for (int i = 0; i < ANV_IMAGE_MEMORY_BINDING_END; ++i) {
854 accum_ranges[i] = (struct anv_image_memory_range) {
855 .binding = i,
856 };
857 }
858
859 for (uint32_t p = 0; p < image->n_planes; ++p) {
860 const struct anv_image_plane *plane = &image->planes[p];
861
862 /* The binding that must contain the plane's primary surface. */
863 const enum anv_image_memory_binding primary_binding = image->disjoint
864 ? ANV_IMAGE_MEMORY_BINDING_PLANE_0 + p
865 : ANV_IMAGE_MEMORY_BINDING_MAIN;
866
867 /* Aliasing is incompatible with the private binding because it does not
868 * live in a VkDeviceMemory.
869 */
870 assert(!(image->vk.create_flags & VK_IMAGE_CREATE_ALIAS_BIT) ||
871 image->bindings[ANV_IMAGE_MEMORY_BINDING_PRIVATE].memory_range.size == 0);
872
873 /* Check primary surface */
874 check_memory_range(accum_ranges,
875 .test_surface = &plane->primary_surface,
876 .expect_binding = primary_binding);
877
878 /* Check shadow surface */
879 if (anv_surface_is_valid(&plane->shadow_surface)) {
880 check_memory_range(accum_ranges,
881 .test_surface = &plane->shadow_surface,
882 .expect_binding = primary_binding);
883 }
884
885 /* Check aux_surface */
886 if (anv_surface_is_valid(&plane->aux_surface)) {
887 enum anv_image_memory_binding binding = primary_binding;
888
889 if (image->vk.drm_format_mod != DRM_FORMAT_MOD_INVALID &&
890 !isl_drm_modifier_has_aux(image->vk.drm_format_mod))
891 binding = ANV_IMAGE_MEMORY_BINDING_PRIVATE;
892
893 /* Display hardware requires that the aux surface start at
894 * a higher address than the primary surface. The 3D hardware
895 * doesn't care, but we enforce the display requirement in case
896 * the image is sent to display.
897 */
898 check_memory_range(accum_ranges,
899 .test_surface = &plane->aux_surface,
900 .expect_binding = binding);
901 }
902
903 /* Check fast clear state */
904 if (plane->fast_clear_memory_range.size > 0) {
905 enum anv_image_memory_binding binding = primary_binding;
906
907 if (image->vk.drm_format_mod != DRM_FORMAT_MOD_INVALID)
908 binding = ANV_IMAGE_MEMORY_BINDING_PRIVATE;
909
910 /* We believe that 256B alignment may be sufficient, but we choose 4K
911 * due to lack of testing. And MI_LOAD/STORE operations require
912 * dword-alignment.
913 */
914 assert(plane->fast_clear_memory_range.alignment == 4096);
915 check_memory_range(accum_ranges,
916 .test_range = &plane->fast_clear_memory_range,
917 .expect_binding = binding);
918 }
919 }
920 #endif
921 }
922
923 /**
924 * Check that the fully-initialized anv_image is compatible with its DRM format
925 * modifier.
926 *
927 * Checking compatibility at the end of image creation is prudent, not
928 * superfluous, because usage of modifiers triggers numerous special cases
929 * throughout queries and image creation, and because
930 * vkGetPhysicalDeviceImageFormatProperties2 has difficulty detecting all
931 * incompatibilities.
932 *
933 * Return VK_ERROR_UNKNOWN if the incompatibility is difficult to detect in
934 * vkGetPhysicalDeviceImageFormatProperties2. Otherwise, assert fail.
935 *
936 * Ideally, if vkGetPhysicalDeviceImageFormatProperties2() succeeds with a given
937 * modifier, then vkCreateImage() produces an image that is compatible with the
938 * modifier. However, it is difficult to reconcile the two functions to agree
939 * due to their complexity. For example, isl_surf_get_ccs_surf() may
940 * unexpectedly fail in vkCreateImage(), eliminating the image's aux surface
941 * even when the modifier requires one. (Maybe we should reconcile the two
942 * functions despite the difficulty).
943 */
944 static VkResult MUST_CHECK
check_drm_format_mod(const struct anv_device * device,const struct anv_image * image)945 check_drm_format_mod(const struct anv_device *device,
946 const struct anv_image *image)
947 {
948 /* Image must have a modifier if and only if it has modifier tiling. */
949 assert((image->vk.drm_format_mod != DRM_FORMAT_MOD_INVALID) ==
950 (image->vk.tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT));
951
952 if (image->vk.drm_format_mod == DRM_FORMAT_MOD_INVALID)
953 return VK_SUCCESS;
954
955 const struct isl_drm_modifier_info *isl_mod_info =
956 isl_drm_modifier_get_info(image->vk.drm_format_mod);
957
958 /* Driver must support the modifier. */
959 assert(isl_drm_modifier_get_score(&device->info, isl_mod_info->modifier));
960
961 /* Enforced by us, not the Vulkan spec. */
962 assert(image->vk.image_type == VK_IMAGE_TYPE_2D);
963 assert(!(image->vk.aspects & VK_IMAGE_ASPECT_DEPTH_BIT));
964 assert(!(image->vk.aspects & VK_IMAGE_ASPECT_STENCIL_BIT));
965 assert(image->vk.mip_levels == 1);
966 assert(image->vk.array_layers == 1);
967 assert(image->vk.samples == 1);
968
969 for (int i = 0; i < image->n_planes; ++i) {
970 const struct anv_image_plane *plane = &image->planes[i];
971 ASSERTED const struct isl_format_layout *isl_layout =
972 isl_format_get_layout(plane->primary_surface.isl.format);
973
974 /* Enforced by us, not the Vulkan spec. */
975 assert(isl_layout->txc == ISL_TXC_NONE);
976 assert(isl_layout->colorspace == ISL_COLORSPACE_LINEAR ||
977 isl_layout->colorspace == ISL_COLORSPACE_SRGB);
978 assert(!anv_surface_is_valid(&plane->shadow_surface));
979
980 if (isl_mod_info->aux_usage != ISL_AUX_USAGE_NONE) {
981 /* Reject DISJOINT for consistency with the GL driver. */
982 assert(!image->disjoint);
983
984 /* The modifier's required aux usage mandates the image's aux usage.
985 * The inverse, however, does not hold; if the modifier has no aux
986 * usage, then we may enable a private aux surface.
987 */
988 if (plane->aux_usage != isl_mod_info->aux_usage) {
989 return vk_errorf(device, VK_ERROR_UNKNOWN,
990 "image with modifier unexpectedly has wrong aux "
991 "usage");
992 }
993 }
994 }
995
996 return VK_SUCCESS;
997 }
998
999 /**
1000 * Use when the app does not provide
1001 * VkImageDrmFormatModifierExplicitCreateInfoEXT.
1002 */
1003 static VkResult MUST_CHECK
add_all_surfaces_implicit_layout(struct anv_device * device,struct anv_image * image,const VkImageFormatListCreateInfo * format_list_info,uint32_t stride,isl_tiling_flags_t isl_tiling_flags,const struct anv_image_create_info * create_info)1004 add_all_surfaces_implicit_layout(
1005 struct anv_device *device,
1006 struct anv_image *image,
1007 const VkImageFormatListCreateInfo *format_list_info,
1008 uint32_t stride,
1009 isl_tiling_flags_t isl_tiling_flags,
1010 const struct anv_image_create_info *create_info)
1011 {
1012 assert(create_info);
1013 const struct intel_device_info *devinfo = &device->info;
1014 isl_surf_usage_flags_t isl_extra_usage_flags =
1015 create_info->isl_extra_usage_flags;
1016 VkResult result;
1017
1018 u_foreach_bit(b, image->vk.aspects) {
1019 VkImageAspectFlagBits aspect = 1 << b;
1020 const uint32_t plane = anv_image_aspect_to_plane(image, aspect);
1021 const struct anv_format_plane plane_format =
1022 anv_get_format_plane(devinfo, image->vk.format, plane, image->vk.tiling);
1023
1024 VkImageUsageFlags vk_usage = vk_image_usage(&image->vk, aspect);
1025 isl_surf_usage_flags_t isl_usage =
1026 choose_isl_surf_usage(image->vk.create_flags, vk_usage,
1027 isl_extra_usage_flags, aspect);
1028
1029 /* Must call this before adding any surfaces because it may modify
1030 * isl_tiling_flags.
1031 */
1032 bool needs_shadow =
1033 anv_image_plane_needs_shadow_surface(devinfo, plane_format,
1034 image->vk.tiling, vk_usage,
1035 image->vk.create_flags,
1036 &isl_tiling_flags);
1037
1038 result = add_primary_surface(device, image, plane, plane_format,
1039 ANV_OFFSET_IMPLICIT, stride,
1040 isl_tiling_flags, isl_usage);
1041 if (result != VK_SUCCESS)
1042 return result;
1043
1044 if (needs_shadow) {
1045 result = add_shadow_surface(device, image, plane, plane_format,
1046 stride, vk_usage);
1047 if (result != VK_SUCCESS)
1048 return result;
1049 }
1050
1051 /* Disable aux if image supports export without modifiers. */
1052 if (image->vk.external_handle_types != 0 &&
1053 image->vk.tiling != VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT)
1054 continue;
1055
1056 result = add_aux_surface_if_supported(device, image, plane, plane_format,
1057 format_list_info,
1058 ANV_OFFSET_IMPLICIT, stride,
1059 isl_extra_usage_flags);
1060 if (result != VK_SUCCESS)
1061 return result;
1062 }
1063
1064 return VK_SUCCESS;
1065 }
1066
1067 /**
1068 * Use when the app provides VkImageDrmFormatModifierExplicitCreateInfoEXT.
1069 */
1070 static VkResult
add_all_surfaces_explicit_layout(struct anv_device * device,struct anv_image * image,const VkImageFormatListCreateInfo * format_list_info,const VkImageDrmFormatModifierExplicitCreateInfoEXT * drm_info,isl_tiling_flags_t isl_tiling_flags,isl_surf_usage_flags_t isl_extra_usage_flags)1071 add_all_surfaces_explicit_layout(
1072 struct anv_device *device,
1073 struct anv_image *image,
1074 const VkImageFormatListCreateInfo *format_list_info,
1075 const VkImageDrmFormatModifierExplicitCreateInfoEXT *drm_info,
1076 isl_tiling_flags_t isl_tiling_flags,
1077 isl_surf_usage_flags_t isl_extra_usage_flags)
1078 {
1079 const struct intel_device_info *devinfo = &device->info;
1080 const uint32_t mod_plane_count = drm_info->drmFormatModifierPlaneCount;
1081 const bool mod_has_aux =
1082 isl_drm_modifier_has_aux(drm_info->drmFormatModifier);
1083 VkResult result;
1084
1085 /* About valid usage in the Vulkan spec:
1086 *
1087 * Unlike vanilla vkCreateImage, which produces undefined behavior on user
1088 * error, here the spec requires the implementation to return
1089 * VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT if the app provides
1090 * a bad plane layout. However, the spec does require
1091 * drmFormatModifierPlaneCount to be valid.
1092 *
1093 * Most validation of plane layout occurs in add_surface().
1094 */
1095
1096 /* We support a restricted set of images with modifiers.
1097 *
1098 * With aux usage,
1099 * - Format plane count must be 1.
1100 * - Memory plane count must be 2.
1101 * Without aux usage,
1102 * - Each format plane must map to a distint memory plane.
1103 *
1104 * For the other cases, currently there is no way to properly map memory
1105 * planes to format planes and aux planes due to the lack of defined ABI
1106 * for external multi-planar images.
1107 */
1108 if (image->n_planes == 1)
1109 assert(image->vk.aspects == VK_IMAGE_ASPECT_COLOR_BIT);
1110 else
1111 assert(!(image->vk.aspects & ~VK_IMAGE_ASPECT_PLANES_BITS_ANV));
1112
1113 if (mod_has_aux)
1114 assert(image->n_planes == 1 && mod_plane_count == 2);
1115 else
1116 assert(image->n_planes == mod_plane_count);
1117
1118 /* Reject special values in the app-provided plane layouts. */
1119 for (uint32_t i = 0; i < mod_plane_count; ++i) {
1120 if (drm_info->pPlaneLayouts[i].rowPitch == 0) {
1121 return vk_errorf(device,
1122 VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT,
1123 "VkImageDrmFormatModifierExplicitCreateInfoEXT::"
1124 "pPlaneLayouts[%u]::rowPitch is 0", i);
1125 }
1126
1127 if (drm_info->pPlaneLayouts[i].offset == ANV_OFFSET_IMPLICIT) {
1128 return vk_errorf(device,
1129 VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT,
1130 "VkImageDrmFormatModifierExplicitCreateInfoEXT::"
1131 "pPlaneLayouts[%u]::offset is %" PRIu64,
1132 i, ANV_OFFSET_IMPLICIT);
1133 }
1134 }
1135
1136 u_foreach_bit(b, image->vk.aspects) {
1137 const VkImageAspectFlagBits aspect = 1 << b;
1138 const uint32_t plane = anv_image_aspect_to_plane(image, aspect);
1139 const struct anv_format_plane format_plane =
1140 anv_get_format_plane(devinfo, image->vk.format, plane, image->vk.tiling);
1141 const VkSubresourceLayout *primary_layout = &drm_info->pPlaneLayouts[plane];
1142
1143 result = add_primary_surface(device, image, plane,
1144 format_plane,
1145 primary_layout->offset,
1146 primary_layout->rowPitch,
1147 isl_tiling_flags,
1148 isl_extra_usage_flags);
1149 if (result != VK_SUCCESS)
1150 return result;
1151
1152 if (!mod_has_aux) {
1153 /* Even though the modifier does not support aux, try to create
1154 * a driver-private aux to improve performance.
1155 */
1156 result = add_aux_surface_if_supported(device, image, plane,
1157 format_plane,
1158 format_list_info,
1159 ANV_OFFSET_IMPLICIT, 0,
1160 isl_extra_usage_flags);
1161 if (result != VK_SUCCESS)
1162 return result;
1163 } else {
1164 const VkSubresourceLayout *aux_layout = &drm_info->pPlaneLayouts[1];
1165 result = add_aux_surface_if_supported(device, image, plane,
1166 format_plane,
1167 format_list_info,
1168 aux_layout->offset,
1169 aux_layout->rowPitch,
1170 isl_extra_usage_flags);
1171 if (result != VK_SUCCESS)
1172 return result;
1173 }
1174 }
1175
1176 return VK_SUCCESS;
1177 }
1178
1179 static const struct isl_drm_modifier_info *
choose_drm_format_mod(const struct anv_physical_device * device,uint32_t modifier_count,const uint64_t * modifiers)1180 choose_drm_format_mod(const struct anv_physical_device *device,
1181 uint32_t modifier_count, const uint64_t *modifiers)
1182 {
1183 uint64_t best_mod = UINT64_MAX;
1184 uint32_t best_score = 0;
1185
1186 for (uint32_t i = 0; i < modifier_count; ++i) {
1187 uint32_t score = isl_drm_modifier_get_score(&device->info, modifiers[i]);
1188 if (score > best_score) {
1189 best_mod = modifiers[i];
1190 best_score = score;
1191 }
1192 }
1193
1194 if (best_score > 0)
1195 return isl_drm_modifier_get_info(best_mod);
1196 else
1197 return NULL;
1198 }
1199
1200 static VkImageUsageFlags
anv_image_create_usage(const VkImageCreateInfo * pCreateInfo,VkImageUsageFlags usage)1201 anv_image_create_usage(const VkImageCreateInfo *pCreateInfo,
1202 VkImageUsageFlags usage)
1203 {
1204 /* Add TRANSFER_SRC usage for multisample attachment images. This is
1205 * because we might internally use the TRANSFER_SRC layout on them for
1206 * blorp operations associated with resolving those into other attachments
1207 * at the end of a subpass.
1208 *
1209 * Without this additional usage, we compute an incorrect AUX state in
1210 * anv_layout_to_aux_state().
1211 */
1212 if (pCreateInfo->samples > VK_SAMPLE_COUNT_1_BIT &&
1213 (usage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
1214 VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)))
1215 usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1216 return usage;
1217 }
1218
1219 static VkResult MUST_CHECK
alloc_private_binding(struct anv_device * device,struct anv_image * image,const VkImageCreateInfo * create_info)1220 alloc_private_binding(struct anv_device *device,
1221 struct anv_image *image,
1222 const VkImageCreateInfo *create_info)
1223 {
1224 struct anv_image_binding *binding =
1225 &image->bindings[ANV_IMAGE_MEMORY_BINDING_PRIVATE];
1226
1227 if (binding->memory_range.size == 0)
1228 return VK_SUCCESS;
1229
1230 const VkImageSwapchainCreateInfoKHR *swapchain_info =
1231 vk_find_struct_const(create_info->pNext, IMAGE_SWAPCHAIN_CREATE_INFO_KHR);
1232
1233 if (swapchain_info && swapchain_info->swapchain != VK_NULL_HANDLE) {
1234 /* The image will be bound to swapchain memory. */
1235 return VK_SUCCESS;
1236 }
1237
1238 return anv_device_alloc_bo(device, "image-binding-private",
1239 binding->memory_range.size, 0, 0,
1240 &binding->address.bo);
1241 }
1242
1243 VkResult
anv_image_init(struct anv_device * device,struct anv_image * image,const struct anv_image_create_info * create_info)1244 anv_image_init(struct anv_device *device, struct anv_image *image,
1245 const struct anv_image_create_info *create_info)
1246 {
1247 const VkImageCreateInfo *pCreateInfo = create_info->vk_info;
1248 const struct VkImageDrmFormatModifierExplicitCreateInfoEXT *mod_explicit_info = NULL;
1249 const struct isl_drm_modifier_info *isl_mod_info = NULL;
1250 VkResult r;
1251
1252 vk_image_init(&device->vk, &image->vk, pCreateInfo);
1253
1254 image->vk.usage = anv_image_create_usage(pCreateInfo, image->vk.usage);
1255 image->vk.stencil_usage =
1256 anv_image_create_usage(pCreateInfo, image->vk.stencil_usage);
1257
1258 if (pCreateInfo->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) {
1259 assert(!image->vk.wsi_legacy_scanout);
1260 mod_explicit_info =
1261 vk_find_struct_const(pCreateInfo->pNext,
1262 IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT);
1263 if (mod_explicit_info) {
1264 isl_mod_info = isl_drm_modifier_get_info(mod_explicit_info->drmFormatModifier);
1265 } else {
1266 const struct VkImageDrmFormatModifierListCreateInfoEXT *mod_list_info =
1267 vk_find_struct_const(pCreateInfo->pNext,
1268 IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT);
1269 isl_mod_info = choose_drm_format_mod(device->physical,
1270 mod_list_info->drmFormatModifierCount,
1271 mod_list_info->pDrmFormatModifiers);
1272 }
1273
1274 assert(isl_mod_info);
1275 assert(image->vk.drm_format_mod == DRM_FORMAT_MOD_INVALID);
1276 image->vk.drm_format_mod = isl_mod_info->modifier;
1277 }
1278
1279 for (int i = 0; i < ANV_IMAGE_MEMORY_BINDING_END; ++i) {
1280 image->bindings[i] = (struct anv_image_binding) {
1281 .memory_range = { .binding = i },
1282 };
1283 }
1284
1285 /* In case of AHardwareBuffer import, we don't know the layout yet */
1286 if (image->vk.external_handle_types &
1287 VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID) {
1288 image->from_ahb = true;
1289 return VK_SUCCESS;
1290 }
1291
1292 image->n_planes = anv_get_format_planes(image->vk.format);
1293
1294 /* The Vulkan 1.2.165 glossary says:
1295 *
1296 * A disjoint image consists of multiple disjoint planes, and is created
1297 * with the VK_IMAGE_CREATE_DISJOINT_BIT bit set.
1298 */
1299 image->disjoint = image->n_planes > 1 &&
1300 (pCreateInfo->flags & VK_IMAGE_CREATE_DISJOINT_BIT);
1301
1302 const isl_tiling_flags_t isl_tiling_flags =
1303 choose_isl_tiling_flags(&device->info, create_info, isl_mod_info,
1304 image->vk.wsi_legacy_scanout);
1305
1306 const VkImageFormatListCreateInfoKHR *fmt_list =
1307 vk_find_struct_const(pCreateInfo->pNext,
1308 IMAGE_FORMAT_LIST_CREATE_INFO_KHR);
1309
1310 if (mod_explicit_info) {
1311 r = add_all_surfaces_explicit_layout(device, image, fmt_list,
1312 mod_explicit_info, isl_tiling_flags,
1313 create_info->isl_extra_usage_flags);
1314 } else {
1315 r = add_all_surfaces_implicit_layout(device, image, fmt_list, 0,
1316 isl_tiling_flags,
1317 create_info);
1318 }
1319
1320 if (r != VK_SUCCESS)
1321 goto fail;
1322
1323 r = alloc_private_binding(device, image, pCreateInfo);
1324 if (r != VK_SUCCESS)
1325 goto fail;
1326
1327 check_memory_bindings(device, image);
1328
1329 r = check_drm_format_mod(device, image);
1330 if (r != VK_SUCCESS)
1331 goto fail;
1332
1333 return VK_SUCCESS;
1334
1335 fail:
1336 vk_image_finish(&image->vk);
1337 return r;
1338 }
1339
1340 void
anv_image_finish(struct anv_image * image)1341 anv_image_finish(struct anv_image *image)
1342 {
1343 struct anv_device *device =
1344 container_of(image->vk.base.device, struct anv_device, vk);
1345
1346 if (image->from_gralloc) {
1347 assert(!image->disjoint);
1348 assert(image->n_planes == 1);
1349 assert(image->planes[0].primary_surface.memory_range.binding ==
1350 ANV_IMAGE_MEMORY_BINDING_MAIN);
1351 assert(image->bindings[ANV_IMAGE_MEMORY_BINDING_MAIN].address.bo != NULL);
1352 anv_device_release_bo(device, image->bindings[ANV_IMAGE_MEMORY_BINDING_MAIN].address.bo);
1353 }
1354
1355 struct anv_bo *private_bo = image->bindings[ANV_IMAGE_MEMORY_BINDING_PRIVATE].address.bo;
1356 if (private_bo)
1357 anv_device_release_bo(device, private_bo);
1358
1359 vk_image_finish(&image->vk);
1360 }
1361
1362 static struct anv_image *
anv_swapchain_get_image(VkSwapchainKHR swapchain,uint32_t index)1363 anv_swapchain_get_image(VkSwapchainKHR swapchain,
1364 uint32_t index)
1365 {
1366 uint32_t n_images = index + 1;
1367 VkImage *images = malloc(sizeof(*images) * n_images);
1368 VkResult result = wsi_common_get_images(swapchain, &n_images, images);
1369
1370 if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
1371 free(images);
1372 return NULL;
1373 }
1374
1375 ANV_FROM_HANDLE(anv_image, image, images[index]);
1376 free(images);
1377
1378 return image;
1379 }
1380
1381 static VkResult
anv_image_init_from_swapchain(struct anv_device * device,struct anv_image * image,const VkImageCreateInfo * pCreateInfo,const VkImageSwapchainCreateInfoKHR * swapchain_info)1382 anv_image_init_from_swapchain(struct anv_device *device,
1383 struct anv_image *image,
1384 const VkImageCreateInfo *pCreateInfo,
1385 const VkImageSwapchainCreateInfoKHR *swapchain_info)
1386 {
1387 struct anv_image *swapchain_image = anv_swapchain_get_image(swapchain_info->swapchain, 0);
1388 assert(swapchain_image);
1389
1390 VkImageCreateInfo local_create_info = *pCreateInfo;
1391 local_create_info.pNext = NULL;
1392
1393 /* Added by wsi code. */
1394 local_create_info.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
1395
1396 /* The spec requires TILING_OPTIMAL as input, but the swapchain image may
1397 * privately use a different tiling. See spec anchor
1398 * #swapchain-wsi-image-create-info .
1399 */
1400 assert(local_create_info.tiling == VK_IMAGE_TILING_OPTIMAL);
1401 local_create_info.tiling = swapchain_image->vk.tiling;
1402
1403 VkImageDrmFormatModifierListCreateInfoEXT local_modifier_info = {
1404 .sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT,
1405 .drmFormatModifierCount = 1,
1406 .pDrmFormatModifiers = &swapchain_image->vk.drm_format_mod,
1407 };
1408
1409 if (swapchain_image->vk.drm_format_mod != DRM_FORMAT_MOD_INVALID)
1410 __vk_append_struct(&local_create_info, &local_modifier_info);
1411
1412 assert(swapchain_image->vk.image_type == local_create_info.imageType);
1413 assert(swapchain_image->vk.format == local_create_info.format);
1414 assert(swapchain_image->vk.extent.width == local_create_info.extent.width);
1415 assert(swapchain_image->vk.extent.height == local_create_info.extent.height);
1416 assert(swapchain_image->vk.extent.depth == local_create_info.extent.depth);
1417 assert(swapchain_image->vk.array_layers == local_create_info.arrayLayers);
1418 assert(swapchain_image->vk.samples == local_create_info.samples);
1419 assert(swapchain_image->vk.tiling == local_create_info.tiling);
1420 assert(swapchain_image->vk.usage == local_create_info.usage);
1421
1422 return anv_image_init(device, image,
1423 &(struct anv_image_create_info) {
1424 .vk_info = &local_create_info,
1425 });
1426 }
1427
1428 static VkResult
anv_image_init_from_create_info(struct anv_device * device,struct anv_image * image,const VkImageCreateInfo * pCreateInfo)1429 anv_image_init_from_create_info(struct anv_device *device,
1430 struct anv_image *image,
1431 const VkImageCreateInfo *pCreateInfo)
1432 {
1433 const VkNativeBufferANDROID *gralloc_info =
1434 vk_find_struct_const(pCreateInfo->pNext, NATIVE_BUFFER_ANDROID);
1435 if (gralloc_info)
1436 return anv_image_init_from_gralloc(device, image, pCreateInfo,
1437 gralloc_info);
1438
1439 #ifndef VK_USE_PLATFORM_ANDROID_KHR
1440 /* Ignore swapchain creation info on Android. Since we don't have an
1441 * implementation in Mesa, we're guaranteed to access an Android object
1442 * incorrectly.
1443 */
1444 const VkImageSwapchainCreateInfoKHR *swapchain_info =
1445 vk_find_struct_const(pCreateInfo->pNext, IMAGE_SWAPCHAIN_CREATE_INFO_KHR);
1446 if (swapchain_info && swapchain_info->swapchain != VK_NULL_HANDLE) {
1447 return anv_image_init_from_swapchain(device, image, pCreateInfo,
1448 swapchain_info);
1449 }
1450 #endif
1451
1452 return anv_image_init(device, image,
1453 &(struct anv_image_create_info) {
1454 .vk_info = pCreateInfo,
1455 });
1456 }
1457
anv_CreateImage(VkDevice _device,const VkImageCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkImage * pImage)1458 VkResult anv_CreateImage(
1459 VkDevice _device,
1460 const VkImageCreateInfo* pCreateInfo,
1461 const VkAllocationCallbacks* pAllocator,
1462 VkImage* pImage)
1463 {
1464 ANV_FROM_HANDLE(anv_device, device, _device);
1465
1466 struct anv_image *image =
1467 vk_object_zalloc(&device->vk, pAllocator, sizeof(*image),
1468 VK_OBJECT_TYPE_IMAGE);
1469 if (!image)
1470 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
1471
1472 VkResult result = anv_image_init_from_create_info(device, image,
1473 pCreateInfo);
1474 if (result != VK_SUCCESS) {
1475 vk_object_free(&device->vk, pAllocator, image);
1476 return result;
1477 }
1478
1479 *pImage = anv_image_to_handle(image);
1480
1481 return result;
1482 }
1483
1484 void
anv_DestroyImage(VkDevice _device,VkImage _image,const VkAllocationCallbacks * pAllocator)1485 anv_DestroyImage(VkDevice _device, VkImage _image,
1486 const VkAllocationCallbacks *pAllocator)
1487 {
1488 ANV_FROM_HANDLE(anv_device, device, _device);
1489 ANV_FROM_HANDLE(anv_image, image, _image);
1490
1491 if (!image)
1492 return;
1493
1494 assert(&device->vk == image->vk.base.device);
1495 anv_image_finish(image);
1496
1497 vk_free2(&device->vk.alloc, pAllocator, image);
1498 }
1499
1500 /* We are binding AHardwareBuffer. Get a description, resolve the
1501 * format and prepare anv_image properly.
1502 */
1503 static void
resolve_ahw_image(struct anv_device * device,struct anv_image * image,struct anv_device_memory * mem)1504 resolve_ahw_image(struct anv_device *device,
1505 struct anv_image *image,
1506 struct anv_device_memory *mem)
1507 {
1508 #if defined(ANDROID) && ANDROID_API_LEVEL >= 26
1509 assert(mem->ahw);
1510 AHardwareBuffer_Desc desc;
1511 AHardwareBuffer_describe(mem->ahw, &desc);
1512 VkResult result;
1513
1514 /* Check tiling. */
1515 int i915_tiling = anv_gem_get_tiling(device, mem->bo->gem_handle);
1516 VkImageTiling vk_tiling;
1517 isl_tiling_flags_t isl_tiling_flags = 0;
1518
1519 switch (i915_tiling) {
1520 case I915_TILING_NONE:
1521 vk_tiling = VK_IMAGE_TILING_LINEAR;
1522 isl_tiling_flags = ISL_TILING_LINEAR_BIT;
1523 break;
1524 case I915_TILING_X:
1525 vk_tiling = VK_IMAGE_TILING_OPTIMAL;
1526 isl_tiling_flags = ISL_TILING_X_BIT;
1527 break;
1528 case I915_TILING_Y:
1529 vk_tiling = VK_IMAGE_TILING_OPTIMAL;
1530 isl_tiling_flags = ISL_TILING_Y0_BIT;
1531 break;
1532 case -1:
1533 default:
1534 unreachable("Invalid tiling flags.");
1535 }
1536
1537 assert(vk_tiling == VK_IMAGE_TILING_LINEAR ||
1538 vk_tiling == VK_IMAGE_TILING_OPTIMAL);
1539
1540 /* Check format. */
1541 VkFormat vk_format = vk_format_from_android(desc.format, desc.usage);
1542 enum isl_format isl_fmt = anv_get_isl_format(&device->info,
1543 vk_format,
1544 VK_IMAGE_ASPECT_COLOR_BIT,
1545 vk_tiling);
1546 assert(isl_fmt != ISL_FORMAT_UNSUPPORTED);
1547
1548 /* Handle RGB(X)->RGBA fallback. */
1549 switch (desc.format) {
1550 case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
1551 case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
1552 if (isl_format_is_rgb(isl_fmt))
1553 isl_fmt = isl_format_rgb_to_rgba(isl_fmt);
1554 break;
1555 }
1556
1557 /* Now we are able to fill anv_image fields properly and create
1558 * isl_surface for it.
1559 */
1560 vk_image_set_format(&image->vk, vk_format);
1561 image->n_planes = anv_get_format_planes(image->vk.format);
1562
1563 uint32_t stride = desc.stride *
1564 (isl_format_get_layout(isl_fmt)->bpb / 8);
1565
1566 struct anv_image_create_info create_info = {
1567 .isl_extra_usage_flags = ISL_SURF_USAGE_DISABLE_AUX_BIT,
1568 };
1569
1570 result = add_all_surfaces_implicit_layout(device, image, NULL, stride,
1571 isl_tiling_flags,
1572 &create_info);
1573 assert(result == VK_SUCCESS);
1574 #endif
1575 }
1576
1577 void
anv_image_get_memory_requirements(struct anv_device * device,struct anv_image * image,VkImageAspectFlags aspects,VkMemoryRequirements2 * pMemoryRequirements)1578 anv_image_get_memory_requirements(struct anv_device *device,
1579 struct anv_image *image,
1580 VkImageAspectFlags aspects,
1581 VkMemoryRequirements2 *pMemoryRequirements)
1582 {
1583 /* The Vulkan spec (git aaed022) says:
1584 *
1585 * memoryTypeBits is a bitfield and contains one bit set for every
1586 * supported memory type for the resource. The bit `1<<i` is set if and
1587 * only if the memory type `i` in the VkPhysicalDeviceMemoryProperties
1588 * structure for the physical device is supported.
1589 *
1590 * All types are currently supported for images.
1591 */
1592 uint32_t memory_types = (1ull << device->physical->memory.type_count) - 1;
1593
1594 vk_foreach_struct(ext, pMemoryRequirements->pNext) {
1595 switch (ext->sType) {
1596 case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: {
1597 VkMemoryDedicatedRequirements *requirements = (void *)ext;
1598 if (image->vk.wsi_legacy_scanout || image->from_ahb) {
1599 /* If we need to set the tiling for external consumers, we need a
1600 * dedicated allocation.
1601 *
1602 * See also anv_AllocateMemory.
1603 */
1604 requirements->prefersDedicatedAllocation = true;
1605 requirements->requiresDedicatedAllocation = true;
1606 } else {
1607 requirements->prefersDedicatedAllocation = false;
1608 requirements->requiresDedicatedAllocation = false;
1609 }
1610 break;
1611 }
1612
1613 default:
1614 anv_debug_ignored_stype(ext->sType);
1615 break;
1616 }
1617 }
1618
1619 /* If the image is disjoint, then we must return the memory requirements for
1620 * the single plane specified in VkImagePlaneMemoryRequirementsInfo. If
1621 * non-disjoint, then exactly one set of memory requirements exists for the
1622 * whole image.
1623 *
1624 * This is enforced by the Valid Usage for VkImageMemoryRequirementsInfo2,
1625 * which requires that the app provide VkImagePlaneMemoryRequirementsInfo if
1626 * and only if the image is disjoint (that is, multi-planar format and
1627 * VK_IMAGE_CREATE_DISJOINT_BIT).
1628 */
1629 const struct anv_image_binding *binding;
1630 if (image->disjoint) {
1631 assert(util_bitcount(aspects) == 1);
1632 assert(aspects & image->vk.aspects);
1633 binding = image_aspect_to_binding(image, aspects);
1634 } else {
1635 assert(aspects == image->vk.aspects);
1636 binding = &image->bindings[ANV_IMAGE_MEMORY_BINDING_MAIN];
1637 }
1638
1639 pMemoryRequirements->memoryRequirements = (VkMemoryRequirements) {
1640 .size = binding->memory_range.size,
1641 .alignment = binding->memory_range.alignment,
1642 .memoryTypeBits = memory_types,
1643 };
1644 }
1645
anv_GetImageMemoryRequirements2(VkDevice _device,const VkImageMemoryRequirementsInfo2 * pInfo,VkMemoryRequirements2 * pMemoryRequirements)1646 void anv_GetImageMemoryRequirements2(
1647 VkDevice _device,
1648 const VkImageMemoryRequirementsInfo2* pInfo,
1649 VkMemoryRequirements2* pMemoryRequirements)
1650 {
1651 ANV_FROM_HANDLE(anv_device, device, _device);
1652 ANV_FROM_HANDLE(anv_image, image, pInfo->image);
1653
1654 VkImageAspectFlags aspects = image->vk.aspects;
1655
1656 vk_foreach_struct_const(ext, pInfo->pNext) {
1657 switch (ext->sType) {
1658 case VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO: {
1659 assert(image->disjoint);
1660 const VkImagePlaneMemoryRequirementsInfo *plane_reqs =
1661 (const VkImagePlaneMemoryRequirementsInfo *) ext;
1662 aspects = plane_reqs->planeAspect;
1663 break;
1664 }
1665
1666 default:
1667 anv_debug_ignored_stype(ext->sType);
1668 break;
1669 }
1670 }
1671
1672 anv_image_get_memory_requirements(device, image, aspects,
1673 pMemoryRequirements);
1674 }
1675
anv_GetDeviceImageMemoryRequirementsKHR(VkDevice _device,const VkDeviceImageMemoryRequirementsKHR * pInfo,VkMemoryRequirements2 * pMemoryRequirements)1676 void anv_GetDeviceImageMemoryRequirementsKHR(
1677 VkDevice _device,
1678 const VkDeviceImageMemoryRequirementsKHR* pInfo,
1679 VkMemoryRequirements2* pMemoryRequirements)
1680 {
1681 ANV_FROM_HANDLE(anv_device, device, _device);
1682 struct anv_image image = { 0 };
1683
1684 ASSERTED VkResult result =
1685 anv_image_init_from_create_info(device, &image, pInfo->pCreateInfo);
1686 assert(result == VK_SUCCESS);
1687
1688 VkImageAspectFlags aspects =
1689 image.disjoint ? pInfo->planeAspect : image.vk.aspects;
1690
1691 anv_image_get_memory_requirements(device, &image, aspects,
1692 pMemoryRequirements);
1693 }
1694
anv_GetImageSparseMemoryRequirements(VkDevice device,VkImage image,uint32_t * pSparseMemoryRequirementCount,VkSparseImageMemoryRequirements * pSparseMemoryRequirements)1695 void anv_GetImageSparseMemoryRequirements(
1696 VkDevice device,
1697 VkImage image,
1698 uint32_t* pSparseMemoryRequirementCount,
1699 VkSparseImageMemoryRequirements* pSparseMemoryRequirements)
1700 {
1701 *pSparseMemoryRequirementCount = 0;
1702 }
1703
anv_GetImageSparseMemoryRequirements2(VkDevice device,const VkImageSparseMemoryRequirementsInfo2 * pInfo,uint32_t * pSparseMemoryRequirementCount,VkSparseImageMemoryRequirements2 * pSparseMemoryRequirements)1704 void anv_GetImageSparseMemoryRequirements2(
1705 VkDevice device,
1706 const VkImageSparseMemoryRequirementsInfo2* pInfo,
1707 uint32_t* pSparseMemoryRequirementCount,
1708 VkSparseImageMemoryRequirements2* pSparseMemoryRequirements)
1709 {
1710 *pSparseMemoryRequirementCount = 0;
1711 }
1712
anv_GetDeviceImageSparseMemoryRequirementsKHR(VkDevice device,const VkDeviceImageMemoryRequirementsKHR * pInfo,uint32_t * pSparseMemoryRequirementCount,VkSparseImageMemoryRequirements2 * pSparseMemoryRequirements)1713 void anv_GetDeviceImageSparseMemoryRequirementsKHR(
1714 VkDevice device,
1715 const VkDeviceImageMemoryRequirementsKHR* pInfo,
1716 uint32_t* pSparseMemoryRequirementCount,
1717 VkSparseImageMemoryRequirements2* pSparseMemoryRequirements)
1718 {
1719 *pSparseMemoryRequirementCount = 0;
1720 }
1721
anv_BindImageMemory2(VkDevice _device,uint32_t bindInfoCount,const VkBindImageMemoryInfo * pBindInfos)1722 VkResult anv_BindImageMemory2(
1723 VkDevice _device,
1724 uint32_t bindInfoCount,
1725 const VkBindImageMemoryInfo* pBindInfos)
1726 {
1727 ANV_FROM_HANDLE(anv_device, device, _device);
1728
1729 for (uint32_t i = 0; i < bindInfoCount; i++) {
1730 const VkBindImageMemoryInfo *bind_info = &pBindInfos[i];
1731 ANV_FROM_HANDLE(anv_device_memory, mem, bind_info->memory);
1732 ANV_FROM_HANDLE(anv_image, image, bind_info->image);
1733 bool did_bind = false;
1734
1735 /* Resolve will alter the image's aspects, do this first. */
1736 if (mem && mem->ahw)
1737 resolve_ahw_image(device, image, mem);
1738
1739 vk_foreach_struct_const(s, bind_info->pNext) {
1740 switch (s->sType) {
1741 case VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO: {
1742 const VkBindImagePlaneMemoryInfo *plane_info =
1743 (const VkBindImagePlaneMemoryInfo *) s;
1744
1745 /* Workaround for possible spec bug.
1746 *
1747 * Unlike VkImagePlaneMemoryRequirementsInfo, which requires that
1748 * the image be disjoint (that is, multi-planar format and
1749 * VK_IMAGE_CREATE_DISJOINT_BIT), VkBindImagePlaneMemoryInfo allows
1750 * the image to be non-disjoint and requires only that the image
1751 * have the DISJOINT flag. In this case, regardless of the value of
1752 * VkImagePlaneMemoryRequirementsInfo::planeAspect, the behavior is
1753 * the same as if VkImagePlaneMemoryRequirementsInfo were omitted.
1754 */
1755 if (!image->disjoint)
1756 break;
1757
1758 struct anv_image_binding *binding =
1759 image_aspect_to_binding(image, plane_info->planeAspect);
1760
1761 binding->address = (struct anv_address) {
1762 .bo = mem->bo,
1763 .offset = bind_info->memoryOffset,
1764 };
1765
1766 did_bind = true;
1767 break;
1768 }
1769 case VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR: {
1770 /* Ignore this struct on Android, we cannot access swapchain
1771 * structures threre.
1772 */
1773 #ifndef VK_USE_PLATFORM_ANDROID_KHR
1774 const VkBindImageMemorySwapchainInfoKHR *swapchain_info =
1775 (const VkBindImageMemorySwapchainInfoKHR *) s;
1776 struct anv_image *swapchain_image =
1777 anv_swapchain_get_image(swapchain_info->swapchain,
1778 swapchain_info->imageIndex);
1779 assert(swapchain_image);
1780 assert(image->vk.aspects == swapchain_image->vk.aspects);
1781 assert(mem == NULL);
1782
1783 for (int j = 0; j < ARRAY_SIZE(image->bindings); ++j)
1784 image->bindings[j].address = swapchain_image->bindings[j].address;
1785
1786 /* We must bump the private binding's bo's refcount because, unlike the other
1787 * bindings, its lifetime is not application-managed.
1788 */
1789 struct anv_bo *private_bo =
1790 image->bindings[ANV_IMAGE_MEMORY_BINDING_PRIVATE].address.bo;
1791 if (private_bo)
1792 anv_bo_ref(private_bo);
1793
1794 did_bind = true;
1795 #endif
1796 break;
1797 }
1798 #pragma GCC diagnostic push
1799 #pragma GCC diagnostic ignored "-Wswitch"
1800 case VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID: {
1801 const VkNativeBufferANDROID *gralloc_info =
1802 (const VkNativeBufferANDROID *)s;
1803 VkResult result = anv_image_bind_from_gralloc(device, image,
1804 gralloc_info);
1805 if (result != VK_SUCCESS)
1806 return result;
1807 did_bind = true;
1808 break;
1809 }
1810 #pragma GCC diagnostic pop
1811 default:
1812 anv_debug_ignored_stype(s->sType);
1813 break;
1814 }
1815 }
1816
1817 if (!did_bind) {
1818 assert(!image->disjoint);
1819
1820 image->bindings[ANV_IMAGE_MEMORY_BINDING_MAIN].address =
1821 (struct anv_address) {
1822 .bo = mem->bo,
1823 .offset = bind_info->memoryOffset,
1824 };
1825
1826 did_bind = true;
1827 }
1828
1829 /* On platforms that use implicit CCS, if the plane's bo lacks implicit
1830 * CCS then disable compression on the plane.
1831 */
1832 for (int p = 0; p < image->n_planes; ++p) {
1833 enum anv_image_memory_binding binding =
1834 image->planes[p].primary_surface.memory_range.binding;
1835 const struct anv_bo *bo =
1836 image->bindings[binding].address.bo;
1837
1838 if (bo && !bo->has_implicit_ccs &&
1839 device->physical->has_implicit_ccs)
1840 image->planes[p].aux_usage = ISL_AUX_USAGE_NONE;
1841 }
1842 }
1843
1844 return VK_SUCCESS;
1845 }
1846
anv_GetImageSubresourceLayout(VkDevice device,VkImage _image,const VkImageSubresource * subresource,VkSubresourceLayout * layout)1847 void anv_GetImageSubresourceLayout(
1848 VkDevice device,
1849 VkImage _image,
1850 const VkImageSubresource* subresource,
1851 VkSubresourceLayout* layout)
1852 {
1853 ANV_FROM_HANDLE(anv_image, image, _image);
1854 const struct anv_surface *surface;
1855
1856 assert(__builtin_popcount(subresource->aspectMask) == 1);
1857
1858 /* The Vulkan spec requires that aspectMask be
1859 * VK_IMAGE_ASPECT_MEMORY_PLANE_i_BIT_EXT if tiling is
1860 * VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT.
1861 *
1862 * For swapchain images, the Vulkan spec says that every swapchain image has
1863 * tiling VK_IMAGE_TILING_OPTIMAL, but we may choose
1864 * VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT internally. Vulkan doesn't allow
1865 * vkGetImageSubresourceLayout for images with VK_IMAGE_TILING_OPTIMAL,
1866 * therefore it's invalid for the application to call this on a swapchain
1867 * image. The WSI code, however, knows when it has internally created
1868 * a swapchain image with VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT,
1869 * so it _should_ correctly use VK_IMAGE_ASPECT_MEMORY_PLANE_* in that case.
1870 * But it incorrectly uses VK_IMAGE_ASPECT_PLANE_*, so we have a temporary
1871 * workaround.
1872 */
1873 if (image->vk.tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) {
1874 /* TODO(chadv): Drop this workaround when WSI gets fixed. */
1875 uint32_t mem_plane;
1876 switch (subresource->aspectMask) {
1877 case VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT:
1878 case VK_IMAGE_ASPECT_PLANE_0_BIT:
1879 mem_plane = 0;
1880 break;
1881 case VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT:
1882 case VK_IMAGE_ASPECT_PLANE_1_BIT:
1883 mem_plane = 1;
1884 break;
1885 case VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT:
1886 case VK_IMAGE_ASPECT_PLANE_2_BIT:
1887 mem_plane = 2;
1888 break;
1889 default:
1890 unreachable("bad VkImageAspectFlags");
1891 }
1892
1893 if (mem_plane == 1 && isl_drm_modifier_has_aux(image->vk.drm_format_mod)) {
1894 assert(image->n_planes == 1);
1895 /* If the memory binding differs between primary and aux, then the
1896 * returned offset will be incorrect.
1897 */
1898 assert(image->planes[0].aux_surface.memory_range.binding ==
1899 image->planes[0].primary_surface.memory_range.binding);
1900 surface = &image->planes[0].aux_surface;
1901 } else {
1902 assert(mem_plane < image->n_planes);
1903 surface = &image->planes[mem_plane].primary_surface;
1904 }
1905 } else {
1906 const uint32_t plane =
1907 anv_image_aspect_to_plane(image, subresource->aspectMask);
1908 surface = &image->planes[plane].primary_surface;
1909 }
1910
1911 layout->offset = surface->memory_range.offset;
1912 layout->rowPitch = surface->isl.row_pitch_B;
1913 layout->depthPitch = isl_surf_get_array_pitch(&surface->isl);
1914 layout->arrayPitch = isl_surf_get_array_pitch(&surface->isl);
1915
1916 if (subresource->mipLevel > 0 || subresource->arrayLayer > 0) {
1917 assert(surface->isl.tiling == ISL_TILING_LINEAR);
1918
1919 uint64_t offset_B;
1920 isl_surf_get_image_offset_B_tile_sa(&surface->isl,
1921 subresource->mipLevel,
1922 subresource->arrayLayer,
1923 0 /* logical_z_offset_px */,
1924 &offset_B, NULL, NULL);
1925 layout->offset += offset_B;
1926 layout->size = layout->rowPitch * anv_minify(image->vk.extent.height,
1927 subresource->mipLevel) *
1928 image->vk.extent.depth;
1929 } else {
1930 layout->size = surface->memory_range.size;
1931 }
1932 }
1933
1934 /**
1935 * This function returns the assumed isl_aux_state for a given VkImageLayout.
1936 * Because Vulkan image layouts don't map directly to isl_aux_state enums, the
1937 * returned enum is the assumed worst case.
1938 *
1939 * @param devinfo The device information of the Intel GPU.
1940 * @param image The image that may contain a collection of buffers.
1941 * @param aspect The aspect of the image to be accessed.
1942 * @param layout The current layout of the image aspect(s).
1943 *
1944 * @return The primary buffer that should be used for the given layout.
1945 */
1946 enum isl_aux_state ATTRIBUTE_PURE
anv_layout_to_aux_state(const struct intel_device_info * const devinfo,const struct anv_image * const image,const VkImageAspectFlagBits aspect,const VkImageLayout layout)1947 anv_layout_to_aux_state(const struct intel_device_info * const devinfo,
1948 const struct anv_image * const image,
1949 const VkImageAspectFlagBits aspect,
1950 const VkImageLayout layout)
1951 {
1952 /* Validate the inputs. */
1953
1954 /* The devinfo is needed as the optimal buffer varies across generations. */
1955 assert(devinfo != NULL);
1956
1957 /* The layout of a NULL image is not properly defined. */
1958 assert(image != NULL);
1959
1960 /* The aspect must be exactly one of the image aspects. */
1961 assert(util_bitcount(aspect) == 1 && (aspect & image->vk.aspects));
1962
1963 /* Determine the optimal buffer. */
1964
1965 const uint32_t plane = anv_image_aspect_to_plane(image, aspect);
1966
1967 /* If we don't have an aux buffer then aux state makes no sense */
1968 const enum isl_aux_usage aux_usage = image->planes[plane].aux_usage;
1969 assert(aux_usage != ISL_AUX_USAGE_NONE);
1970
1971 /* All images that use an auxiliary surface are required to be tiled. */
1972 assert(image->planes[plane].primary_surface.isl.tiling != ISL_TILING_LINEAR);
1973
1974 /* Handle a few special cases */
1975 switch (layout) {
1976 /* Invalid layouts */
1977 case VK_IMAGE_LAYOUT_MAX_ENUM:
1978 unreachable("Invalid image layout.");
1979
1980 /* Undefined layouts
1981 *
1982 * The pre-initialized layout is equivalent to the undefined layout for
1983 * optimally-tiled images. We can only do color compression (CCS or HiZ)
1984 * on tiled images.
1985 */
1986 case VK_IMAGE_LAYOUT_UNDEFINED:
1987 case VK_IMAGE_LAYOUT_PREINITIALIZED:
1988 return ISL_AUX_STATE_AUX_INVALID;
1989
1990 case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR: {
1991 assert(image->vk.aspects == VK_IMAGE_ASPECT_COLOR_BIT);
1992
1993 enum isl_aux_state aux_state =
1994 isl_drm_modifier_get_default_aux_state(image->vk.drm_format_mod);
1995
1996 switch (aux_state) {
1997 default:
1998 assert(!"unexpected isl_aux_state");
1999 case ISL_AUX_STATE_AUX_INVALID:
2000 /* The modifier does not support compression. But, if we arrived
2001 * here, then we have enabled compression on it anyway, in which case
2002 * we must resolve the aux surface before we release ownership to the
2003 * presentation engine (because, having no modifier, the presentation
2004 * engine will not be aware of the aux surface). The presentation
2005 * engine will not access the aux surface (because it is unware of
2006 * it), and so the aux surface will still be resolved when we
2007 * re-acquire ownership.
2008 *
2009 * Therefore, at ownership transfers in either direction, there does
2010 * exist an aux surface despite the lack of modifier and its state is
2011 * pass-through.
2012 */
2013 return ISL_AUX_STATE_PASS_THROUGH;
2014 case ISL_AUX_STATE_COMPRESSED_NO_CLEAR:
2015 return ISL_AUX_STATE_COMPRESSED_NO_CLEAR;
2016 }
2017 }
2018
2019 default:
2020 break;
2021 }
2022
2023 const bool read_only = vk_image_layout_is_read_only(layout, aspect);
2024
2025 const VkImageUsageFlags image_aspect_usage =
2026 vk_image_usage(&image->vk, aspect);
2027 const VkImageUsageFlags usage =
2028 vk_image_layout_to_usage_flags(layout, aspect) & image_aspect_usage;
2029
2030 bool aux_supported = true;
2031 bool clear_supported = isl_aux_usage_has_fast_clears(aux_usage);
2032
2033 const struct isl_format_layout *fmtl =
2034 isl_format_get_layout(image->planes[plane].primary_surface.isl.format);
2035
2036 /* Disabling CCS for the following case avoids failures in:
2037 * - dEQP-VK.drm_format_modifiers.export_import.*
2038 * - dEQP-VK.synchronization*
2039 */
2040 if (usage & (VK_IMAGE_USAGE_TRANSFER_DST_BIT |
2041 VK_IMAGE_USAGE_TRANSFER_SRC_BIT) && fmtl->bpb <= 16 &&
2042 aux_usage == ISL_AUX_USAGE_CCS_E && devinfo->ver >= 12) {
2043 aux_supported = false;
2044 clear_supported = false;
2045 }
2046
2047 if ((usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) && !read_only) {
2048 /* This image could be used as both an input attachment and a render
2049 * target (depth, stencil, or color) at the same time and this can cause
2050 * corruption.
2051 *
2052 * We currently only disable aux in this way for depth even though we
2053 * disable it for color in GL.
2054 *
2055 * TODO: Should we be disabling this in more cases?
2056 */
2057 if (aspect == VK_IMAGE_ASPECT_DEPTH_BIT && devinfo->ver <= 9) {
2058 aux_supported = false;
2059 clear_supported = false;
2060 }
2061 }
2062
2063 if (usage & VK_IMAGE_USAGE_STORAGE_BIT) {
2064 aux_supported = false;
2065 clear_supported = false;
2066 }
2067
2068 if (usage & (VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
2069 VK_IMAGE_USAGE_SAMPLED_BIT |
2070 VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) {
2071 switch (aux_usage) {
2072 case ISL_AUX_USAGE_HIZ:
2073 if (!anv_can_sample_with_hiz(devinfo, image)) {
2074 aux_supported = false;
2075 clear_supported = false;
2076 }
2077 break;
2078
2079 case ISL_AUX_USAGE_HIZ_CCS:
2080 aux_supported = false;
2081 clear_supported = false;
2082 break;
2083
2084 case ISL_AUX_USAGE_HIZ_CCS_WT:
2085 break;
2086
2087 case ISL_AUX_USAGE_CCS_D:
2088 aux_supported = false;
2089 clear_supported = false;
2090 break;
2091
2092 case ISL_AUX_USAGE_MCS:
2093 if (!anv_can_sample_mcs_with_clear(devinfo, image))
2094 clear_supported = false;
2095 break;
2096
2097 case ISL_AUX_USAGE_CCS_E:
2098 case ISL_AUX_USAGE_STC_CCS:
2099 break;
2100
2101 default:
2102 unreachable("Unsupported aux usage");
2103 }
2104 }
2105
2106 switch (aux_usage) {
2107 case ISL_AUX_USAGE_HIZ:
2108 case ISL_AUX_USAGE_HIZ_CCS:
2109 case ISL_AUX_USAGE_HIZ_CCS_WT:
2110 if (aux_supported) {
2111 assert(clear_supported);
2112 return ISL_AUX_STATE_COMPRESSED_CLEAR;
2113 } else if (read_only) {
2114 return ISL_AUX_STATE_RESOLVED;
2115 } else {
2116 return ISL_AUX_STATE_AUX_INVALID;
2117 }
2118
2119 case ISL_AUX_USAGE_CCS_D:
2120 /* We only support clear in exactly one state */
2121 if (layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) {
2122 assert(aux_supported);
2123 assert(clear_supported);
2124 return ISL_AUX_STATE_PARTIAL_CLEAR;
2125 } else {
2126 return ISL_AUX_STATE_PASS_THROUGH;
2127 }
2128
2129 case ISL_AUX_USAGE_CCS_E:
2130 if (aux_supported) {
2131 assert(clear_supported);
2132 return ISL_AUX_STATE_COMPRESSED_CLEAR;
2133 } else {
2134 return ISL_AUX_STATE_PASS_THROUGH;
2135 }
2136
2137 case ISL_AUX_USAGE_MCS:
2138 assert(aux_supported);
2139 if (clear_supported) {
2140 return ISL_AUX_STATE_COMPRESSED_CLEAR;
2141 } else {
2142 return ISL_AUX_STATE_COMPRESSED_NO_CLEAR;
2143 }
2144
2145 case ISL_AUX_USAGE_STC_CCS:
2146 assert(aux_supported);
2147 assert(!clear_supported);
2148 return ISL_AUX_STATE_COMPRESSED_NO_CLEAR;
2149
2150 default:
2151 unreachable("Unsupported aux usage");
2152 }
2153 }
2154
2155 /**
2156 * This function determines the optimal buffer to use for a given
2157 * VkImageLayout and other pieces of information needed to make that
2158 * determination. This does not determine the optimal buffer to use
2159 * during a resolve operation.
2160 *
2161 * @param devinfo The device information of the Intel GPU.
2162 * @param image The image that may contain a collection of buffers.
2163 * @param aspect The aspect of the image to be accessed.
2164 * @param usage The usage which describes how the image will be accessed.
2165 * @param layout The current layout of the image aspect(s).
2166 *
2167 * @return The primary buffer that should be used for the given layout.
2168 */
2169 enum isl_aux_usage ATTRIBUTE_PURE
anv_layout_to_aux_usage(const struct intel_device_info * const devinfo,const struct anv_image * const image,const VkImageAspectFlagBits aspect,const VkImageUsageFlagBits usage,const VkImageLayout layout)2170 anv_layout_to_aux_usage(const struct intel_device_info * const devinfo,
2171 const struct anv_image * const image,
2172 const VkImageAspectFlagBits aspect,
2173 const VkImageUsageFlagBits usage,
2174 const VkImageLayout layout)
2175 {
2176 const uint32_t plane = anv_image_aspect_to_plane(image, aspect);
2177
2178 /* If there is no auxiliary surface allocated, we must use the one and only
2179 * main buffer.
2180 */
2181 if (image->planes[plane].aux_usage == ISL_AUX_USAGE_NONE)
2182 return ISL_AUX_USAGE_NONE;
2183
2184 enum isl_aux_state aux_state =
2185 anv_layout_to_aux_state(devinfo, image, aspect, layout);
2186
2187 switch (aux_state) {
2188 case ISL_AUX_STATE_CLEAR:
2189 unreachable("We never use this state");
2190
2191 case ISL_AUX_STATE_PARTIAL_CLEAR:
2192 assert(image->vk.aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT_ANV);
2193 assert(image->planes[plane].aux_usage == ISL_AUX_USAGE_CCS_D);
2194 assert(image->vk.samples == 1);
2195 return ISL_AUX_USAGE_CCS_D;
2196
2197 case ISL_AUX_STATE_COMPRESSED_CLEAR:
2198 case ISL_AUX_STATE_COMPRESSED_NO_CLEAR:
2199 return image->planes[plane].aux_usage;
2200
2201 case ISL_AUX_STATE_RESOLVED:
2202 /* We can only use RESOLVED in read-only layouts because any write will
2203 * either land us in AUX_INVALID or COMPRESSED_NO_CLEAR. We can do
2204 * writes in PASS_THROUGH without destroying it so that is allowed.
2205 */
2206 assert(vk_image_layout_is_read_only(layout, aspect));
2207 assert(util_is_power_of_two_or_zero(usage));
2208 if (usage == VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
2209 /* If we have valid HiZ data and are using the image as a read-only
2210 * depth/stencil attachment, we should enable HiZ so that we can get
2211 * faster depth testing.
2212 */
2213 return image->planes[plane].aux_usage;
2214 } else {
2215 return ISL_AUX_USAGE_NONE;
2216 }
2217
2218 case ISL_AUX_STATE_PASS_THROUGH:
2219 case ISL_AUX_STATE_AUX_INVALID:
2220 return ISL_AUX_USAGE_NONE;
2221 }
2222
2223 unreachable("Invalid isl_aux_state");
2224 }
2225
2226 /**
2227 * This function returns the level of unresolved fast-clear support of the
2228 * given image in the given VkImageLayout.
2229 *
2230 * @param devinfo The device information of the Intel GPU.
2231 * @param image The image that may contain a collection of buffers.
2232 * @param aspect The aspect of the image to be accessed.
2233 * @param usage The usage which describes how the image will be accessed.
2234 * @param layout The current layout of the image aspect(s).
2235 */
2236 enum anv_fast_clear_type ATTRIBUTE_PURE
anv_layout_to_fast_clear_type(const struct intel_device_info * const devinfo,const struct anv_image * const image,const VkImageAspectFlagBits aspect,const VkImageLayout layout)2237 anv_layout_to_fast_clear_type(const struct intel_device_info * const devinfo,
2238 const struct anv_image * const image,
2239 const VkImageAspectFlagBits aspect,
2240 const VkImageLayout layout)
2241 {
2242 if (INTEL_DEBUG(DEBUG_NO_FAST_CLEAR))
2243 return ANV_FAST_CLEAR_NONE;
2244
2245 const uint32_t plane = anv_image_aspect_to_plane(image, aspect);
2246
2247 /* If there is no auxiliary surface allocated, there are no fast-clears */
2248 if (image->planes[plane].aux_usage == ISL_AUX_USAGE_NONE)
2249 return ANV_FAST_CLEAR_NONE;
2250
2251 /* We don't support MSAA fast-clears on Ivybridge or Bay Trail because they
2252 * lack the MI ALU which we need to determine the predicates.
2253 */
2254 if (devinfo->verx10 == 70 && image->vk.samples > 1)
2255 return ANV_FAST_CLEAR_NONE;
2256
2257 enum isl_aux_state aux_state =
2258 anv_layout_to_aux_state(devinfo, image, aspect, layout);
2259
2260 switch (aux_state) {
2261 case ISL_AUX_STATE_CLEAR:
2262 unreachable("We never use this state");
2263
2264 case ISL_AUX_STATE_PARTIAL_CLEAR:
2265 case ISL_AUX_STATE_COMPRESSED_CLEAR:
2266 if (aspect == VK_IMAGE_ASPECT_DEPTH_BIT) {
2267 return ANV_FAST_CLEAR_DEFAULT_VALUE;
2268 } else if (devinfo->ver >= 12 &&
2269 image->planes[plane].aux_usage == ISL_AUX_USAGE_CCS_E) {
2270 /* On TGL, if a block of fragment shader outputs match the surface's
2271 * clear color, the HW may convert them to fast-clears (see HSD
2272 * 14010672564). This can lead to rendering corruptions if not
2273 * handled properly. We restrict the clear color to zero to avoid
2274 * issues that can occur with:
2275 * - Texture view rendering (including blorp_copy calls)
2276 * - Images with multiple levels or array layers
2277 */
2278 return ANV_FAST_CLEAR_DEFAULT_VALUE;
2279 } else if (layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) {
2280 /* When we're in a render pass we have the clear color data from the
2281 * VkRenderPassBeginInfo and we can use arbitrary clear colors. They
2282 * must get partially resolved before we leave the render pass.
2283 */
2284 return ANV_FAST_CLEAR_ANY;
2285 } else if (image->planes[plane].aux_usage == ISL_AUX_USAGE_MCS ||
2286 image->planes[plane].aux_usage == ISL_AUX_USAGE_CCS_E) {
2287 if (devinfo->ver >= 11) {
2288 /* On ICL and later, the sampler hardware uses a copy of the clear
2289 * value that is encoded as a pixel value. Therefore, we can use
2290 * any clear color we like for sampling.
2291 */
2292 return ANV_FAST_CLEAR_ANY;
2293 } else {
2294 /* If the image has MCS or CCS_E enabled all the time then we can
2295 * use fast-clear as long as the clear color is the default value
2296 * of zero since this is the default value we program into every
2297 * surface state used for texturing.
2298 */
2299 return ANV_FAST_CLEAR_DEFAULT_VALUE;
2300 }
2301 } else {
2302 return ANV_FAST_CLEAR_NONE;
2303 }
2304
2305 case ISL_AUX_STATE_COMPRESSED_NO_CLEAR:
2306 case ISL_AUX_STATE_RESOLVED:
2307 case ISL_AUX_STATE_PASS_THROUGH:
2308 case ISL_AUX_STATE_AUX_INVALID:
2309 return ANV_FAST_CLEAR_NONE;
2310 }
2311
2312 unreachable("Invalid isl_aux_state");
2313 }
2314
2315
2316 static struct anv_state
alloc_surface_state(struct anv_device * device)2317 alloc_surface_state(struct anv_device *device)
2318 {
2319 return anv_state_pool_alloc(&device->surface_state_pool, 64, 64);
2320 }
2321
2322 static enum isl_channel_select
remap_swizzle(VkComponentSwizzle swizzle,struct isl_swizzle format_swizzle)2323 remap_swizzle(VkComponentSwizzle swizzle,
2324 struct isl_swizzle format_swizzle)
2325 {
2326 switch (swizzle) {
2327 case VK_COMPONENT_SWIZZLE_ZERO: return ISL_CHANNEL_SELECT_ZERO;
2328 case VK_COMPONENT_SWIZZLE_ONE: return ISL_CHANNEL_SELECT_ONE;
2329 case VK_COMPONENT_SWIZZLE_R: return format_swizzle.r;
2330 case VK_COMPONENT_SWIZZLE_G: return format_swizzle.g;
2331 case VK_COMPONENT_SWIZZLE_B: return format_swizzle.b;
2332 case VK_COMPONENT_SWIZZLE_A: return format_swizzle.a;
2333 default:
2334 unreachable("Invalid swizzle");
2335 }
2336 }
2337
2338 void
anv_image_fill_surface_state(struct anv_device * device,const struct anv_image * image,VkImageAspectFlagBits aspect,const struct isl_view * view_in,isl_surf_usage_flags_t view_usage,enum isl_aux_usage aux_usage,const union isl_color_value * clear_color,enum anv_image_view_state_flags flags,struct anv_surface_state * state_inout,struct brw_image_param * image_param_out)2339 anv_image_fill_surface_state(struct anv_device *device,
2340 const struct anv_image *image,
2341 VkImageAspectFlagBits aspect,
2342 const struct isl_view *view_in,
2343 isl_surf_usage_flags_t view_usage,
2344 enum isl_aux_usage aux_usage,
2345 const union isl_color_value *clear_color,
2346 enum anv_image_view_state_flags flags,
2347 struct anv_surface_state *state_inout,
2348 struct brw_image_param *image_param_out)
2349 {
2350 const uint32_t plane = anv_image_aspect_to_plane(image, aspect);
2351
2352 const struct anv_surface *surface = &image->planes[plane].primary_surface,
2353 *aux_surface = &image->planes[plane].aux_surface;
2354
2355 struct isl_view view = *view_in;
2356 view.usage |= view_usage;
2357
2358 /* For texturing with VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL from a
2359 * compressed surface with a shadow surface, we use the shadow instead of
2360 * the primary surface. The shadow surface will be tiled, unlike the main
2361 * surface, so it should get significantly better performance.
2362 */
2363 if (anv_surface_is_valid(&image->planes[plane].shadow_surface) &&
2364 isl_format_is_compressed(view.format) &&
2365 (flags & ANV_IMAGE_VIEW_STATE_TEXTURE_OPTIMAL)) {
2366 assert(isl_format_is_compressed(surface->isl.format));
2367 assert(surface->isl.tiling == ISL_TILING_LINEAR);
2368 assert(image->planes[plane].shadow_surface.isl.tiling != ISL_TILING_LINEAR);
2369 surface = &image->planes[plane].shadow_surface;
2370 }
2371
2372 /* For texturing from stencil on gfx7, we have to sample from a shadow
2373 * surface because we don't support W-tiling in the sampler.
2374 */
2375 if (anv_surface_is_valid(&image->planes[plane].shadow_surface) &&
2376 aspect == VK_IMAGE_ASPECT_STENCIL_BIT) {
2377 assert(device->info.ver == 7);
2378 assert(view_usage & ISL_SURF_USAGE_TEXTURE_BIT);
2379 surface = &image->planes[plane].shadow_surface;
2380 }
2381
2382 if (view_usage == ISL_SURF_USAGE_RENDER_TARGET_BIT)
2383 view.swizzle = anv_swizzle_for_render(view.swizzle);
2384
2385 /* On Ivy Bridge and Bay Trail we do the swizzle in the shader */
2386 if (device->info.verx10 == 70)
2387 view.swizzle = ISL_SWIZZLE_IDENTITY;
2388
2389 /* If this is a HiZ buffer we can sample from with a programmable clear
2390 * value (SKL+), define the clear value to the optimal constant.
2391 */
2392 union isl_color_value default_clear_color = { .u32 = { 0, } };
2393 if (device->info.ver >= 9 && aspect == VK_IMAGE_ASPECT_DEPTH_BIT)
2394 default_clear_color.f32[0] = ANV_HZ_FC_VAL;
2395 if (!clear_color)
2396 clear_color = &default_clear_color;
2397
2398 const struct anv_address address =
2399 anv_image_address(image, &surface->memory_range);
2400
2401 if (view_usage == ISL_SURF_USAGE_STORAGE_BIT &&
2402 (flags & ANV_IMAGE_VIEW_STATE_STORAGE_LOWERED) &&
2403 !isl_has_matching_typed_storage_image_format(&device->info,
2404 view.format)) {
2405 /* In this case, we are a writeable storage buffer which needs to be
2406 * lowered to linear. All tiling and offset calculations will be done in
2407 * the shader.
2408 */
2409 assert(aux_usage == ISL_AUX_USAGE_NONE);
2410 isl_buffer_fill_state(&device->isl_dev, state_inout->state.map,
2411 .address = anv_address_physical(address),
2412 .size_B = surface->isl.size_B,
2413 .format = ISL_FORMAT_RAW,
2414 .swizzle = ISL_SWIZZLE_IDENTITY,
2415 .stride_B = 1,
2416 .mocs = anv_mocs(device, address.bo, view_usage));
2417 state_inout->address = address,
2418 state_inout->aux_address = ANV_NULL_ADDRESS;
2419 state_inout->clear_address = ANV_NULL_ADDRESS;
2420 } else {
2421 if (view_usage == ISL_SURF_USAGE_STORAGE_BIT &&
2422 (flags & ANV_IMAGE_VIEW_STATE_STORAGE_LOWERED)) {
2423 /* Typed surface reads support a very limited subset of the shader
2424 * image formats. Translate it into the closest format the hardware
2425 * supports.
2426 */
2427 assert(aux_usage == ISL_AUX_USAGE_NONE);
2428 view.format = isl_lower_storage_image_format(&device->info,
2429 view.format);
2430 }
2431
2432 const struct isl_surf *isl_surf = &surface->isl;
2433
2434 struct isl_surf tmp_surf;
2435 uint64_t offset_B = 0;
2436 uint32_t tile_x_sa = 0, tile_y_sa = 0;
2437 if (isl_format_is_compressed(surface->isl.format) &&
2438 !isl_format_is_compressed(view.format)) {
2439 /* We're creating an uncompressed view of a compressed surface. This
2440 * is allowed but only for a single level/layer.
2441 */
2442 assert(surface->isl.samples == 1);
2443 assert(view.levels == 1);
2444 assert(view.array_len == 1);
2445
2446 ASSERTED bool ok =
2447 isl_surf_get_uncompressed_surf(&device->isl_dev, isl_surf, &view,
2448 &tmp_surf, &view,
2449 &offset_B, &tile_x_sa, &tile_y_sa);
2450 assert(ok);
2451 isl_surf = &tmp_surf;
2452
2453 if (device->info.ver <= 8) {
2454 assert(surface->isl.tiling == ISL_TILING_LINEAR);
2455 assert(tile_x_sa == 0);
2456 assert(tile_y_sa == 0);
2457 }
2458 }
2459
2460 state_inout->address = anv_address_add(address, offset_B);
2461
2462 struct anv_address aux_address = ANV_NULL_ADDRESS;
2463 if (aux_usage != ISL_AUX_USAGE_NONE)
2464 aux_address = anv_image_address(image, &aux_surface->memory_range);
2465 state_inout->aux_address = aux_address;
2466
2467 struct anv_address clear_address = ANV_NULL_ADDRESS;
2468 if (device->info.ver >= 10 && isl_aux_usage_has_fast_clears(aux_usage)) {
2469 clear_address = anv_image_get_clear_color_addr(device, image, aspect);
2470 }
2471 state_inout->clear_address = clear_address;
2472
2473 isl_surf_fill_state(&device->isl_dev, state_inout->state.map,
2474 .surf = isl_surf,
2475 .view = &view,
2476 .address = anv_address_physical(state_inout->address),
2477 .clear_color = *clear_color,
2478 .aux_surf = &aux_surface->isl,
2479 .aux_usage = aux_usage,
2480 .aux_address = anv_address_physical(aux_address),
2481 .clear_address = anv_address_physical(clear_address),
2482 .use_clear_address = !anv_address_is_null(clear_address),
2483 .mocs = anv_mocs(device, state_inout->address.bo,
2484 view_usage),
2485 .x_offset_sa = tile_x_sa,
2486 .y_offset_sa = tile_y_sa);
2487
2488 /* With the exception of gfx8, the bottom 12 bits of the MCS base address
2489 * are used to store other information. This should be ok, however,
2490 * because the surface buffer addresses are always 4K page aligned.
2491 */
2492 if (!anv_address_is_null(aux_address)) {
2493 uint32_t *aux_addr_dw = state_inout->state.map +
2494 device->isl_dev.ss.aux_addr_offset;
2495 assert((aux_address.offset & 0xfff) == 0);
2496 state_inout->aux_address.offset |= *aux_addr_dw & 0xfff;
2497 }
2498
2499 if (device->info.ver >= 10 && clear_address.bo) {
2500 uint32_t *clear_addr_dw = state_inout->state.map +
2501 device->isl_dev.ss.clear_color_state_offset;
2502 assert((clear_address.offset & 0x3f) == 0);
2503 state_inout->clear_address.offset |= *clear_addr_dw & 0x3f;
2504 }
2505 }
2506
2507 if (image_param_out) {
2508 assert(view_usage == ISL_SURF_USAGE_STORAGE_BIT);
2509 isl_surf_fill_image_param(&device->isl_dev, image_param_out,
2510 &surface->isl, &view);
2511 }
2512 }
2513
2514 static uint32_t
anv_image_aspect_get_planes(VkImageAspectFlags aspect_mask)2515 anv_image_aspect_get_planes(VkImageAspectFlags aspect_mask)
2516 {
2517 anv_assert_valid_aspect_set(aspect_mask);
2518 return util_bitcount(aspect_mask);
2519 }
2520
2521 VkResult
anv_CreateImageView(VkDevice _device,const VkImageViewCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkImageView * pView)2522 anv_CreateImageView(VkDevice _device,
2523 const VkImageViewCreateInfo *pCreateInfo,
2524 const VkAllocationCallbacks *pAllocator,
2525 VkImageView *pView)
2526 {
2527 ANV_FROM_HANDLE(anv_device, device, _device);
2528 ANV_FROM_HANDLE(anv_image, image, pCreateInfo->image);
2529 struct anv_image_view *iview;
2530
2531 iview = vk_image_view_create(&device->vk, pCreateInfo,
2532 pAllocator, sizeof(*iview));
2533 if (iview == NULL)
2534 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
2535
2536 iview->image = image;
2537 iview->n_planes = anv_image_aspect_get_planes(iview->vk.aspects);
2538
2539 /* Check if a conversion info was passed. */
2540 const struct anv_format *conv_format = NULL;
2541 const VkSamplerYcbcrConversionInfo *conv_info =
2542 vk_find_struct_const(pCreateInfo->pNext, SAMPLER_YCBCR_CONVERSION_INFO);
2543
2544 #ifdef ANDROID
2545 /* If image has an external format, the pNext chain must contain an
2546 * instance of VKSamplerYcbcrConversionInfo with a conversion object
2547 * created with the same external format as image."
2548 */
2549 assert(!image->vk.android_external_format || conv_info);
2550 #endif
2551
2552 if (conv_info) {
2553 ANV_FROM_HANDLE(anv_ycbcr_conversion, conversion, conv_info->conversion);
2554 conv_format = conversion->format;
2555 }
2556
2557 #ifdef ANDROID
2558 /* "If image has an external format, format must be VK_FORMAT_UNDEFINED." */
2559 assert(!image->vk.android_external_format ||
2560 pCreateInfo->format == VK_FORMAT_UNDEFINED);
2561 #endif
2562
2563 /* Format is undefined, this can happen when using external formats. Set
2564 * view format from the passed conversion info.
2565 */
2566 if (iview->vk.format == VK_FORMAT_UNDEFINED && conv_format)
2567 iview->vk.format = conv_format->vk_format;
2568
2569 /* Now go through the underlying image selected planes and map them to
2570 * planes in the image view.
2571 */
2572 anv_foreach_image_aspect_bit(iaspect_bit, image, iview->vk.aspects) {
2573 const uint32_t iplane =
2574 anv_aspect_to_plane(image->vk.aspects, 1UL << iaspect_bit);
2575 const uint32_t vplane =
2576 anv_aspect_to_plane(iview->vk.aspects, 1UL << iaspect_bit);
2577 struct anv_format_plane format;
2578 format = anv_get_format_plane(&device->info, iview->vk.format,
2579 vplane, image->vk.tiling);
2580
2581 iview->planes[vplane].image_plane = iplane;
2582
2583 iview->planes[vplane].isl = (struct isl_view) {
2584 .format = format.isl_format,
2585 .base_level = iview->vk.base_mip_level,
2586 .levels = iview->vk.level_count,
2587 .base_array_layer = iview->vk.base_array_layer,
2588 .array_len = iview->vk.layer_count,
2589 .swizzle = {
2590 .r = remap_swizzle(iview->vk.swizzle.r, format.swizzle),
2591 .g = remap_swizzle(iview->vk.swizzle.g, format.swizzle),
2592 .b = remap_swizzle(iview->vk.swizzle.b, format.swizzle),
2593 .a = remap_swizzle(iview->vk.swizzle.a, format.swizzle),
2594 },
2595 };
2596
2597 if (pCreateInfo->viewType == VK_IMAGE_VIEW_TYPE_3D) {
2598 iview->planes[vplane].isl.base_array_layer = 0;
2599 iview->planes[vplane].isl.array_len = iview->vk.extent.depth;
2600 }
2601
2602 if (pCreateInfo->viewType == VK_IMAGE_VIEW_TYPE_CUBE ||
2603 pCreateInfo->viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) {
2604 iview->planes[vplane].isl.usage = ISL_SURF_USAGE_CUBE_BIT;
2605 } else {
2606 iview->planes[vplane].isl.usage = 0;
2607 }
2608
2609 if (iview->vk.usage & VK_IMAGE_USAGE_SAMPLED_BIT ||
2610 (iview->vk.usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT &&
2611 !(iview->vk.aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT_ANV))) {
2612 iview->planes[vplane].optimal_sampler_surface_state.state = alloc_surface_state(device);
2613 iview->planes[vplane].general_sampler_surface_state.state = alloc_surface_state(device);
2614
2615 enum isl_aux_usage general_aux_usage =
2616 anv_layout_to_aux_usage(&device->info, image, 1UL << iaspect_bit,
2617 VK_IMAGE_USAGE_SAMPLED_BIT,
2618 VK_IMAGE_LAYOUT_GENERAL);
2619 enum isl_aux_usage optimal_aux_usage =
2620 anv_layout_to_aux_usage(&device->info, image, 1UL << iaspect_bit,
2621 VK_IMAGE_USAGE_SAMPLED_BIT,
2622 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
2623
2624 anv_image_fill_surface_state(device, image, 1ULL << iaspect_bit,
2625 &iview->planes[vplane].isl,
2626 ISL_SURF_USAGE_TEXTURE_BIT,
2627 optimal_aux_usage, NULL,
2628 ANV_IMAGE_VIEW_STATE_TEXTURE_OPTIMAL,
2629 &iview->planes[vplane].optimal_sampler_surface_state,
2630 NULL);
2631
2632 anv_image_fill_surface_state(device, image, 1ULL << iaspect_bit,
2633 &iview->planes[vplane].isl,
2634 ISL_SURF_USAGE_TEXTURE_BIT,
2635 general_aux_usage, NULL,
2636 0,
2637 &iview->planes[vplane].general_sampler_surface_state,
2638 NULL);
2639 }
2640
2641 /* NOTE: This one needs to go last since it may stomp isl_view.format */
2642 if (iview->vk.usage & VK_IMAGE_USAGE_STORAGE_BIT) {
2643 iview->planes[vplane].storage_surface_state.state = alloc_surface_state(device);
2644 anv_image_fill_surface_state(device, image, 1ULL << iaspect_bit,
2645 &iview->planes[vplane].isl,
2646 ISL_SURF_USAGE_STORAGE_BIT,
2647 ISL_AUX_USAGE_NONE, NULL,
2648 0,
2649 &iview->planes[vplane].storage_surface_state,
2650 NULL);
2651
2652 if (isl_is_storage_image_format(format.isl_format)) {
2653 iview->planes[vplane].lowered_storage_surface_state.state =
2654 alloc_surface_state(device);
2655
2656 anv_image_fill_surface_state(device, image, 1ULL << iaspect_bit,
2657 &iview->planes[vplane].isl,
2658 ISL_SURF_USAGE_STORAGE_BIT,
2659 ISL_AUX_USAGE_NONE, NULL,
2660 ANV_IMAGE_VIEW_STATE_STORAGE_LOWERED,
2661 &iview->planes[vplane].lowered_storage_surface_state,
2662 &iview->planes[vplane].lowered_storage_image_param);
2663 } else {
2664 /* In this case, we support the format but, because there's no
2665 * SPIR-V format specifier corresponding to it, we only support it
2666 * if the hardware can do it natively. This is possible for some
2667 * reads but for most writes. Instead of hanging if someone gets
2668 * it wrong, we give them a NULL descriptor.
2669 */
2670 assert(isl_format_supports_typed_writes(&device->info,
2671 format.isl_format));
2672 iview->planes[vplane].lowered_storage_surface_state.state =
2673 device->null_surface_state;
2674 }
2675 }
2676 }
2677
2678 *pView = anv_image_view_to_handle(iview);
2679
2680 return VK_SUCCESS;
2681 }
2682
2683 void
anv_DestroyImageView(VkDevice _device,VkImageView _iview,const VkAllocationCallbacks * pAllocator)2684 anv_DestroyImageView(VkDevice _device, VkImageView _iview,
2685 const VkAllocationCallbacks *pAllocator)
2686 {
2687 ANV_FROM_HANDLE(anv_device, device, _device);
2688 ANV_FROM_HANDLE(anv_image_view, iview, _iview);
2689
2690 if (!iview)
2691 return;
2692
2693 for (uint32_t plane = 0; plane < iview->n_planes; plane++) {
2694 /* Check offset instead of alloc_size because this they might be
2695 * device->null_surface_state which always has offset == 0. We don't
2696 * own that one so we don't want to accidentally free it.
2697 */
2698 if (iview->planes[plane].optimal_sampler_surface_state.state.offset) {
2699 anv_state_pool_free(&device->surface_state_pool,
2700 iview->planes[plane].optimal_sampler_surface_state.state);
2701 }
2702
2703 if (iview->planes[plane].general_sampler_surface_state.state.offset) {
2704 anv_state_pool_free(&device->surface_state_pool,
2705 iview->planes[plane].general_sampler_surface_state.state);
2706 }
2707
2708 if (iview->planes[plane].storage_surface_state.state.offset) {
2709 anv_state_pool_free(&device->surface_state_pool,
2710 iview->planes[plane].storage_surface_state.state);
2711 }
2712
2713 if (iview->planes[plane].lowered_storage_surface_state.state.offset) {
2714 anv_state_pool_free(&device->surface_state_pool,
2715 iview->planes[plane].lowered_storage_surface_state.state);
2716 }
2717 }
2718
2719 vk_image_view_destroy(&device->vk, pAllocator, &iview->vk);
2720 }
2721
2722
2723 VkResult
anv_CreateBufferView(VkDevice _device,const VkBufferViewCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkBufferView * pView)2724 anv_CreateBufferView(VkDevice _device,
2725 const VkBufferViewCreateInfo *pCreateInfo,
2726 const VkAllocationCallbacks *pAllocator,
2727 VkBufferView *pView)
2728 {
2729 ANV_FROM_HANDLE(anv_device, device, _device);
2730 ANV_FROM_HANDLE(anv_buffer, buffer, pCreateInfo->buffer);
2731 struct anv_buffer_view *view;
2732
2733 view = vk_object_alloc(&device->vk, pAllocator, sizeof(*view),
2734 VK_OBJECT_TYPE_BUFFER_VIEW);
2735 if (!view)
2736 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
2737
2738 /* TODO: Handle the format swizzle? */
2739
2740 view->format = anv_get_isl_format(&device->info, pCreateInfo->format,
2741 VK_IMAGE_ASPECT_COLOR_BIT,
2742 VK_IMAGE_TILING_LINEAR);
2743 const uint32_t format_bs = isl_format_get_layout(view->format)->bpb / 8;
2744 view->range = anv_buffer_get_range(buffer, pCreateInfo->offset,
2745 pCreateInfo->range);
2746 view->range = align_down_npot_u32(view->range, format_bs);
2747
2748 view->address = anv_address_add(buffer->address, pCreateInfo->offset);
2749
2750 if (buffer->usage & VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT) {
2751 view->surface_state = alloc_surface_state(device);
2752
2753 anv_fill_buffer_surface_state(device, view->surface_state,
2754 view->format, ISL_SURF_USAGE_TEXTURE_BIT,
2755 view->address, view->range, format_bs);
2756 } else {
2757 view->surface_state = (struct anv_state){ 0 };
2758 }
2759
2760 if (buffer->usage & VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT) {
2761 view->storage_surface_state = alloc_surface_state(device);
2762 view->lowered_storage_surface_state = alloc_surface_state(device);
2763
2764 anv_fill_buffer_surface_state(device, view->storage_surface_state,
2765 view->format, ISL_SURF_USAGE_STORAGE_BIT,
2766 view->address, view->range,
2767 isl_format_get_layout(view->format)->bpb / 8);
2768
2769 enum isl_format lowered_format =
2770 isl_has_matching_typed_storage_image_format(&device->info,
2771 view->format) ?
2772 isl_lower_storage_image_format(&device->info, view->format) :
2773 ISL_FORMAT_RAW;
2774
2775 anv_fill_buffer_surface_state(device, view->lowered_storage_surface_state,
2776 lowered_format, ISL_SURF_USAGE_STORAGE_BIT,
2777 view->address, view->range,
2778 (lowered_format == ISL_FORMAT_RAW ? 1 :
2779 isl_format_get_layout(lowered_format)->bpb / 8));
2780
2781 isl_buffer_fill_image_param(&device->isl_dev,
2782 &view->lowered_storage_image_param,
2783 view->format, view->range);
2784 } else {
2785 view->storage_surface_state = (struct anv_state){ 0 };
2786 view->lowered_storage_surface_state = (struct anv_state){ 0 };
2787 }
2788
2789 *pView = anv_buffer_view_to_handle(view);
2790
2791 return VK_SUCCESS;
2792 }
2793
2794 void
anv_DestroyBufferView(VkDevice _device,VkBufferView bufferView,const VkAllocationCallbacks * pAllocator)2795 anv_DestroyBufferView(VkDevice _device, VkBufferView bufferView,
2796 const VkAllocationCallbacks *pAllocator)
2797 {
2798 ANV_FROM_HANDLE(anv_device, device, _device);
2799 ANV_FROM_HANDLE(anv_buffer_view, view, bufferView);
2800
2801 if (!view)
2802 return;
2803
2804 if (view->surface_state.alloc_size > 0)
2805 anv_state_pool_free(&device->surface_state_pool,
2806 view->surface_state);
2807
2808 if (view->storage_surface_state.alloc_size > 0)
2809 anv_state_pool_free(&device->surface_state_pool,
2810 view->storage_surface_state);
2811
2812 if (view->lowered_storage_surface_state.alloc_size > 0)
2813 anv_state_pool_free(&device->surface_state_pool,
2814 view->lowered_storage_surface_state);
2815
2816 vk_object_free(&device->vk, pAllocator, view);
2817 }
2818