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 (device->info.ver >= 12 &&
639 (image->vk.array_layers > 1 || image->vk.mip_levels)) {
640 /* HSD 14010672564: On TGL, if a block of fragment shader outputs
641 * match the surface's clear color, the HW may convert them to
642 * fast-clears. Anv only does clear color tracking for the first
643 * slice unfortunately. Disable CCS until anv gains more clear color
644 * tracking abilities.
645 */
646 anv_perf_warn(VK_LOG_OBJS(&image->vk.base),
647 "HW may put fast-clear blocks on more slices than SW "
648 "currently tracks. Not allocating a CCS buffer.");
649 return VK_SUCCESS;
650 }
651
652 if (INTEL_DEBUG(DEBUG_NO_RBC))
653 return VK_SUCCESS;
654
655 ok = isl_surf_get_ccs_surf(&device->isl_dev,
656 &image->planes[plane].primary_surface.isl,
657 NULL,
658 &image->planes[plane].aux_surface.isl,
659 stride);
660 if (!ok)
661 return VK_SUCCESS;
662
663 /* Choose aux usage */
664 if (!(image->vk.usage & VK_IMAGE_USAGE_STORAGE_BIT) &&
665 anv_formats_ccs_e_compatible(&device->info,
666 image->vk.create_flags,
667 image->vk.format,
668 image->vk.tiling,
669 fmt_list)) {
670 /* For images created without MUTABLE_FORMAT_BIT set, we know that
671 * they will always be used with the original format. In particular,
672 * they will always be used with a format that supports color
673 * compression. If it's never used as a storage image, then it will
674 * only be used through the sampler or the as a render target. This
675 * means that it's safe to just leave compression on at all times for
676 * these formats.
677 */
678 image->planes[plane].aux_usage = ISL_AUX_USAGE_CCS_E;
679 } else if (device->info.ver >= 12) {
680 anv_perf_warn(VK_LOG_OBJS(&image->vk.base),
681 "The CCS_D aux mode is not yet handled on "
682 "Gfx12+. Not allocating a CCS buffer.");
683 image->planes[plane].aux_surface.isl.size_B = 0;
684 return VK_SUCCESS;
685 } else {
686 image->planes[plane].aux_usage = ISL_AUX_USAGE_CCS_D;
687 }
688
689 if (!device->physical->has_implicit_ccs) {
690 enum anv_image_memory_binding binding =
691 ANV_IMAGE_MEMORY_BINDING_PLANE_0 + plane;
692
693 if (image->vk.drm_format_mod != DRM_FORMAT_MOD_INVALID &&
694 !isl_drm_modifier_has_aux(image->vk.drm_format_mod))
695 binding = ANV_IMAGE_MEMORY_BINDING_PRIVATE;
696
697 result = add_surface(device, image, &image->planes[plane].aux_surface,
698 binding, offset);
699 if (result != VK_SUCCESS)
700 return result;
701 }
702
703 return add_aux_state_tracking_buffer(device, image, plane);
704 } else if ((aspect & VK_IMAGE_ASPECT_ANY_COLOR_BIT_ANV) && image->vk.samples > 1) {
705 assert(!(image->vk.usage & VK_IMAGE_USAGE_STORAGE_BIT));
706 ok = isl_surf_get_mcs_surf(&device->isl_dev,
707 &image->planes[plane].primary_surface.isl,
708 &image->planes[plane].aux_surface.isl);
709 if (!ok)
710 return VK_SUCCESS;
711
712 image->planes[plane].aux_usage = ISL_AUX_USAGE_MCS;
713
714 result = add_surface(device, image, &image->planes[plane].aux_surface,
715 ANV_IMAGE_MEMORY_BINDING_PLANE_0 + plane,
716 ANV_OFFSET_IMPLICIT);
717 if (result != VK_SUCCESS)
718 return result;
719
720 return add_aux_state_tracking_buffer(device, image, plane);
721 }
722
723 return VK_SUCCESS;
724 }
725
726 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)727 add_shadow_surface(struct anv_device *device,
728 struct anv_image *image,
729 uint32_t plane,
730 struct anv_format_plane plane_format,
731 uint32_t stride,
732 VkImageUsageFlags vk_plane_usage)
733 {
734 ASSERTED bool ok;
735
736 ok = isl_surf_init(&device->isl_dev,
737 &image->planes[plane].shadow_surface.isl,
738 .dim = vk_to_isl_surf_dim[image->vk.image_type],
739 .format = plane_format.isl_format,
740 .width = image->vk.extent.width,
741 .height = image->vk.extent.height,
742 .depth = image->vk.extent.depth,
743 .levels = image->vk.mip_levels,
744 .array_len = image->vk.array_layers,
745 .samples = image->vk.samples,
746 .min_alignment_B = 0,
747 .row_pitch_B = stride,
748 .usage = ISL_SURF_USAGE_TEXTURE_BIT |
749 (vk_plane_usage & ISL_SURF_USAGE_CUBE_BIT),
750 .tiling_flags = ISL_TILING_ANY_MASK);
751
752 /* isl_surf_init() will fail only if provided invalid input. Invalid input
753 * here is illegal in Vulkan.
754 */
755 assert(ok);
756
757 return add_surface(device, image, &image->planes[plane].shadow_surface,
758 ANV_IMAGE_MEMORY_BINDING_PLANE_0 + plane,
759 ANV_OFFSET_IMPLICIT);
760 }
761
762 /**
763 * Initialize the anv_image::*_surface selected by \a aspect. Then update the
764 * image's memory requirements (that is, the image's size and alignment).
765 *
766 * @param offset See add_surface()
767 */
768 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)769 add_primary_surface(struct anv_device *device,
770 struct anv_image *image,
771 uint32_t plane,
772 struct anv_format_plane plane_format,
773 uint64_t offset,
774 uint32_t stride,
775 isl_tiling_flags_t isl_tiling_flags,
776 isl_surf_usage_flags_t isl_usage)
777 {
778 struct anv_surface *anv_surf = &image->planes[plane].primary_surface;
779 bool ok;
780
781 ok = isl_surf_init(&device->isl_dev, &anv_surf->isl,
782 .dim = vk_to_isl_surf_dim[image->vk.image_type],
783 .format = plane_format.isl_format,
784 .width = image->vk.extent.width / plane_format.denominator_scales[0],
785 .height = image->vk.extent.height / plane_format.denominator_scales[1],
786 .depth = image->vk.extent.depth,
787 .levels = image->vk.mip_levels,
788 .array_len = image->vk.array_layers,
789 .samples = image->vk.samples,
790 .min_alignment_B = 0,
791 .row_pitch_B = stride,
792 .usage = isl_usage,
793 .tiling_flags = isl_tiling_flags);
794
795 if (!ok) {
796 /* TODO: Should return
797 * VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT in come cases.
798 */
799 return VK_ERROR_OUT_OF_DEVICE_MEMORY;
800 }
801
802 image->planes[plane].aux_usage = ISL_AUX_USAGE_NONE;
803
804 return add_surface(device, image, anv_surf,
805 ANV_IMAGE_MEMORY_BINDING_PLANE_0 + plane, offset);
806 }
807
808 #ifndef NDEBUG
809 static bool MUST_CHECK
memory_range_is_aligned(struct anv_image_memory_range memory_range)810 memory_range_is_aligned(struct anv_image_memory_range memory_range)
811 {
812 return anv_is_aligned(memory_range.offset, memory_range.alignment);
813 }
814 #endif
815
816 struct check_memory_range_params {
817 struct anv_image_memory_range *accum_ranges;
818 const struct anv_surface *test_surface;
819 const struct anv_image_memory_range *test_range;
820 enum anv_image_memory_binding expect_binding;
821 };
822
823 #define check_memory_range(...) \
824 check_memory_range_s(&(struct check_memory_range_params) { __VA_ARGS__ })
825
826 static void UNUSED
check_memory_range_s(const struct check_memory_range_params * p)827 check_memory_range_s(const struct check_memory_range_params *p)
828 {
829 assert((p->test_surface == NULL) != (p->test_range == NULL));
830
831 const struct anv_image_memory_range *test_range =
832 p->test_range ?: &p->test_surface->memory_range;
833
834 struct anv_image_memory_range *accum_range =
835 &p->accum_ranges[p->expect_binding];
836
837 assert(test_range->binding == p->expect_binding);
838 assert(test_range->offset >= memory_range_end(*accum_range));
839 assert(memory_range_is_aligned(*test_range));
840
841 if (p->test_surface) {
842 assert(anv_surface_is_valid(p->test_surface));
843 assert(p->test_surface->memory_range.alignment ==
844 p->test_surface->isl.alignment_B);
845 }
846
847 memory_range_merge(accum_range, *test_range);
848 }
849
850 /**
851 * Validate the image's memory bindings *after* all its surfaces and memory
852 * ranges are final.
853 *
854 * For simplicity's sake, we do not validate free-form layout of the image's
855 * memory bindings. We validate the layout described in the comments of struct
856 * anv_image.
857 */
858 static void
check_memory_bindings(const struct anv_device * device,const struct anv_image * image)859 check_memory_bindings(const struct anv_device *device,
860 const struct anv_image *image)
861 {
862 #ifdef DEBUG
863 /* As we inspect each part of the image, we merge the part's memory range
864 * into these accumulation ranges.
865 */
866 struct anv_image_memory_range accum_ranges[ANV_IMAGE_MEMORY_BINDING_END];
867 for (int i = 0; i < ANV_IMAGE_MEMORY_BINDING_END; ++i) {
868 accum_ranges[i] = (struct anv_image_memory_range) {
869 .binding = i,
870 };
871 }
872
873 for (uint32_t p = 0; p < image->n_planes; ++p) {
874 const struct anv_image_plane *plane = &image->planes[p];
875
876 /* The binding that must contain the plane's primary surface. */
877 const enum anv_image_memory_binding primary_binding = image->disjoint
878 ? ANV_IMAGE_MEMORY_BINDING_PLANE_0 + p
879 : ANV_IMAGE_MEMORY_BINDING_MAIN;
880
881 /* Aliasing is incompatible with the private binding because it does not
882 * live in a VkDeviceMemory.
883 */
884 assert(!(image->vk.create_flags & VK_IMAGE_CREATE_ALIAS_BIT) ||
885 image->bindings[ANV_IMAGE_MEMORY_BINDING_PRIVATE].memory_range.size == 0);
886
887 /* Check primary surface */
888 check_memory_range(accum_ranges,
889 .test_surface = &plane->primary_surface,
890 .expect_binding = primary_binding);
891
892 /* Check shadow surface */
893 if (anv_surface_is_valid(&plane->shadow_surface)) {
894 check_memory_range(accum_ranges,
895 .test_surface = &plane->shadow_surface,
896 .expect_binding = primary_binding);
897 }
898
899 /* Check aux_surface */
900 if (anv_surface_is_valid(&plane->aux_surface)) {
901 enum anv_image_memory_binding binding = primary_binding;
902
903 if (image->vk.drm_format_mod != DRM_FORMAT_MOD_INVALID &&
904 !isl_drm_modifier_has_aux(image->vk.drm_format_mod))
905 binding = ANV_IMAGE_MEMORY_BINDING_PRIVATE;
906
907 /* Display hardware requires that the aux surface start at
908 * a higher address than the primary surface. The 3D hardware
909 * doesn't care, but we enforce the display requirement in case
910 * the image is sent to display.
911 */
912 check_memory_range(accum_ranges,
913 .test_surface = &plane->aux_surface,
914 .expect_binding = binding);
915 }
916
917 /* Check fast clear state */
918 if (plane->fast_clear_memory_range.size > 0) {
919 enum anv_image_memory_binding binding = primary_binding;
920
921 if (image->vk.drm_format_mod != DRM_FORMAT_MOD_INVALID)
922 binding = ANV_IMAGE_MEMORY_BINDING_PRIVATE;
923
924 /* We believe that 256B alignment may be sufficient, but we choose 4K
925 * due to lack of testing. And MI_LOAD/STORE operations require
926 * dword-alignment.
927 */
928 assert(plane->fast_clear_memory_range.alignment == 4096);
929 check_memory_range(accum_ranges,
930 .test_range = &plane->fast_clear_memory_range,
931 .expect_binding = binding);
932 }
933 }
934 #endif
935 }
936
937 /**
938 * Check that the fully-initialized anv_image is compatible with its DRM format
939 * modifier.
940 *
941 * Checking compatibility at the end of image creation is prudent, not
942 * superfluous, because usage of modifiers triggers numerous special cases
943 * throughout queries and image creation, and because
944 * vkGetPhysicalDeviceImageFormatProperties2 has difficulty detecting all
945 * incompatibilities.
946 *
947 * Return VK_ERROR_UNKNOWN if the incompatibility is difficult to detect in
948 * vkGetPhysicalDeviceImageFormatProperties2. Otherwise, assert fail.
949 *
950 * Ideally, if vkGetPhysicalDeviceImageFormatProperties2() succeeds with a given
951 * modifier, then vkCreateImage() produces an image that is compatible with the
952 * modifier. However, it is difficult to reconcile the two functions to agree
953 * due to their complexity. For example, isl_surf_get_ccs_surf() may
954 * unexpectedly fail in vkCreateImage(), eliminating the image's aux surface
955 * even when the modifier requires one. (Maybe we should reconcile the two
956 * functions despite the difficulty).
957 */
958 static VkResult MUST_CHECK
check_drm_format_mod(const struct anv_device * device,const struct anv_image * image)959 check_drm_format_mod(const struct anv_device *device,
960 const struct anv_image *image)
961 {
962 /* Image must have a modifier if and only if it has modifier tiling. */
963 assert((image->vk.drm_format_mod != DRM_FORMAT_MOD_INVALID) ==
964 (image->vk.tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT));
965
966 if (image->vk.drm_format_mod == DRM_FORMAT_MOD_INVALID)
967 return VK_SUCCESS;
968
969 const struct isl_drm_modifier_info *isl_mod_info =
970 isl_drm_modifier_get_info(image->vk.drm_format_mod);
971
972 /* Driver must support the modifier. */
973 assert(isl_drm_modifier_get_score(&device->info, isl_mod_info->modifier));
974
975 /* Enforced by us, not the Vulkan spec. */
976 assert(image->vk.image_type == VK_IMAGE_TYPE_2D);
977 assert(!(image->vk.aspects & VK_IMAGE_ASPECT_DEPTH_BIT));
978 assert(!(image->vk.aspects & VK_IMAGE_ASPECT_STENCIL_BIT));
979 assert(image->vk.mip_levels == 1);
980 assert(image->vk.array_layers == 1);
981 assert(image->vk.samples == 1);
982
983 for (int i = 0; i < image->n_planes; ++i) {
984 const struct anv_image_plane *plane = &image->planes[i];
985 ASSERTED const struct isl_format_layout *isl_layout =
986 isl_format_get_layout(plane->primary_surface.isl.format);
987
988 /* Enforced by us, not the Vulkan spec. */
989 assert(isl_layout->txc == ISL_TXC_NONE);
990 assert(isl_layout->colorspace == ISL_COLORSPACE_LINEAR ||
991 isl_layout->colorspace == ISL_COLORSPACE_SRGB);
992 assert(!anv_surface_is_valid(&plane->shadow_surface));
993
994 if (isl_mod_info->aux_usage != ISL_AUX_USAGE_NONE) {
995 /* Reject DISJOINT for consistency with the GL driver. */
996 assert(!image->disjoint);
997
998 /* The modifier's required aux usage mandates the image's aux usage.
999 * The inverse, however, does not hold; if the modifier has no aux
1000 * usage, then we may enable a private aux surface.
1001 */
1002 if (plane->aux_usage != isl_mod_info->aux_usage) {
1003 return vk_errorf(device, VK_ERROR_UNKNOWN,
1004 "image with modifier unexpectedly has wrong aux "
1005 "usage");
1006 }
1007 }
1008 }
1009
1010 return VK_SUCCESS;
1011 }
1012
1013 /**
1014 * Use when the app does not provide
1015 * VkImageDrmFormatModifierExplicitCreateInfoEXT.
1016 */
1017 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)1018 add_all_surfaces_implicit_layout(
1019 struct anv_device *device,
1020 struct anv_image *image,
1021 const VkImageFormatListCreateInfo *format_list_info,
1022 uint32_t stride,
1023 isl_tiling_flags_t isl_tiling_flags,
1024 const struct anv_image_create_info *create_info)
1025 {
1026 assert(create_info);
1027 const struct intel_device_info *devinfo = &device->info;
1028 isl_surf_usage_flags_t isl_extra_usage_flags =
1029 create_info->isl_extra_usage_flags;
1030 VkResult result;
1031
1032 u_foreach_bit(b, image->vk.aspects) {
1033 VkImageAspectFlagBits aspect = 1 << b;
1034 const uint32_t plane = anv_image_aspect_to_plane(image, aspect);
1035 const struct anv_format_plane plane_format =
1036 anv_get_format_plane(devinfo, image->vk.format, plane, image->vk.tiling);
1037
1038 VkImageUsageFlags vk_usage = vk_image_usage(&image->vk, aspect);
1039 isl_surf_usage_flags_t isl_usage =
1040 choose_isl_surf_usage(image->vk.create_flags, vk_usage,
1041 isl_extra_usage_flags, aspect);
1042
1043 /* Must call this before adding any surfaces because it may modify
1044 * isl_tiling_flags.
1045 */
1046 bool needs_shadow =
1047 anv_image_plane_needs_shadow_surface(devinfo, plane_format,
1048 image->vk.tiling, vk_usage,
1049 image->vk.create_flags,
1050 &isl_tiling_flags);
1051
1052 result = add_primary_surface(device, image, plane, plane_format,
1053 ANV_OFFSET_IMPLICIT, stride,
1054 isl_tiling_flags, isl_usage);
1055 if (result != VK_SUCCESS)
1056 return result;
1057
1058 if (needs_shadow) {
1059 result = add_shadow_surface(device, image, plane, plane_format,
1060 stride, vk_usage);
1061 if (result != VK_SUCCESS)
1062 return result;
1063 }
1064
1065 /* Disable aux if image supports export without modifiers. */
1066 if (image->vk.external_handle_types != 0 &&
1067 image->vk.tiling != VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT)
1068 continue;
1069
1070 result = add_aux_surface_if_supported(device, image, plane, plane_format,
1071 format_list_info,
1072 ANV_OFFSET_IMPLICIT, stride,
1073 isl_extra_usage_flags);
1074 if (result != VK_SUCCESS)
1075 return result;
1076 }
1077
1078 return VK_SUCCESS;
1079 }
1080
1081 /**
1082 * Use when the app provides VkImageDrmFormatModifierExplicitCreateInfoEXT.
1083 */
1084 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)1085 add_all_surfaces_explicit_layout(
1086 struct anv_device *device,
1087 struct anv_image *image,
1088 const VkImageFormatListCreateInfo *format_list_info,
1089 const VkImageDrmFormatModifierExplicitCreateInfoEXT *drm_info,
1090 isl_tiling_flags_t isl_tiling_flags,
1091 isl_surf_usage_flags_t isl_extra_usage_flags)
1092 {
1093 const struct intel_device_info *devinfo = &device->info;
1094 const uint32_t mod_plane_count = drm_info->drmFormatModifierPlaneCount;
1095 const bool mod_has_aux =
1096 isl_drm_modifier_has_aux(drm_info->drmFormatModifier);
1097 VkResult result;
1098
1099 /* About valid usage in the Vulkan spec:
1100 *
1101 * Unlike vanilla vkCreateImage, which produces undefined behavior on user
1102 * error, here the spec requires the implementation to return
1103 * VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT if the app provides
1104 * a bad plane layout. However, the spec does require
1105 * drmFormatModifierPlaneCount to be valid.
1106 *
1107 * Most validation of plane layout occurs in add_surface().
1108 */
1109
1110 /* We support a restricted set of images with modifiers.
1111 *
1112 * With aux usage,
1113 * - Format plane count must be 1.
1114 * - Memory plane count must be 2.
1115 * Without aux usage,
1116 * - Each format plane must map to a distint memory plane.
1117 *
1118 * For the other cases, currently there is no way to properly map memory
1119 * planes to format planes and aux planes due to the lack of defined ABI
1120 * for external multi-planar images.
1121 */
1122 if (image->n_planes == 1)
1123 assert(image->vk.aspects == VK_IMAGE_ASPECT_COLOR_BIT);
1124 else
1125 assert(!(image->vk.aspects & ~VK_IMAGE_ASPECT_PLANES_BITS_ANV));
1126
1127 if (mod_has_aux)
1128 assert(image->n_planes == 1 && mod_plane_count == 2);
1129 else
1130 assert(image->n_planes == mod_plane_count);
1131
1132 /* Reject special values in the app-provided plane layouts. */
1133 for (uint32_t i = 0; i < mod_plane_count; ++i) {
1134 if (drm_info->pPlaneLayouts[i].rowPitch == 0) {
1135 return vk_errorf(device,
1136 VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT,
1137 "VkImageDrmFormatModifierExplicitCreateInfoEXT::"
1138 "pPlaneLayouts[%u]::rowPitch is 0", i);
1139 }
1140
1141 if (drm_info->pPlaneLayouts[i].offset == ANV_OFFSET_IMPLICIT) {
1142 return vk_errorf(device,
1143 VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT,
1144 "VkImageDrmFormatModifierExplicitCreateInfoEXT::"
1145 "pPlaneLayouts[%u]::offset is %" PRIu64,
1146 i, ANV_OFFSET_IMPLICIT);
1147 }
1148 }
1149
1150 u_foreach_bit(b, image->vk.aspects) {
1151 const VkImageAspectFlagBits aspect = 1 << b;
1152 const uint32_t plane = anv_image_aspect_to_plane(image, aspect);
1153 const struct anv_format_plane format_plane =
1154 anv_get_format_plane(devinfo, image->vk.format, plane, image->vk.tiling);
1155 const VkSubresourceLayout *primary_layout = &drm_info->pPlaneLayouts[plane];
1156
1157 result = add_primary_surface(device, image, plane,
1158 format_plane,
1159 primary_layout->offset,
1160 primary_layout->rowPitch,
1161 isl_tiling_flags,
1162 isl_extra_usage_flags);
1163 if (result != VK_SUCCESS)
1164 return result;
1165
1166 if (!mod_has_aux) {
1167 /* Even though the modifier does not support aux, try to create
1168 * a driver-private aux to improve performance.
1169 */
1170 result = add_aux_surface_if_supported(device, image, plane,
1171 format_plane,
1172 format_list_info,
1173 ANV_OFFSET_IMPLICIT, 0,
1174 isl_extra_usage_flags);
1175 if (result != VK_SUCCESS)
1176 return result;
1177 } else {
1178 const VkSubresourceLayout *aux_layout = &drm_info->pPlaneLayouts[1];
1179 result = add_aux_surface_if_supported(device, image, plane,
1180 format_plane,
1181 format_list_info,
1182 aux_layout->offset,
1183 aux_layout->rowPitch,
1184 isl_extra_usage_flags);
1185 if (result != VK_SUCCESS)
1186 return result;
1187 }
1188 }
1189
1190 return VK_SUCCESS;
1191 }
1192
1193 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)1194 choose_drm_format_mod(const struct anv_physical_device *device,
1195 uint32_t modifier_count, const uint64_t *modifiers)
1196 {
1197 uint64_t best_mod = UINT64_MAX;
1198 uint32_t best_score = 0;
1199
1200 for (uint32_t i = 0; i < modifier_count; ++i) {
1201 uint32_t score = isl_drm_modifier_get_score(&device->info, modifiers[i]);
1202 if (score > best_score) {
1203 best_mod = modifiers[i];
1204 best_score = score;
1205 }
1206 }
1207
1208 if (best_score > 0)
1209 return isl_drm_modifier_get_info(best_mod);
1210 else
1211 return NULL;
1212 }
1213
1214 static VkImageUsageFlags
anv_image_create_usage(const VkImageCreateInfo * pCreateInfo,VkImageUsageFlags usage)1215 anv_image_create_usage(const VkImageCreateInfo *pCreateInfo,
1216 VkImageUsageFlags usage)
1217 {
1218 /* Add TRANSFER_SRC usage for multisample attachment images. This is
1219 * because we might internally use the TRANSFER_SRC layout on them for
1220 * blorp operations associated with resolving those into other attachments
1221 * at the end of a subpass.
1222 *
1223 * Without this additional usage, we compute an incorrect AUX state in
1224 * anv_layout_to_aux_state().
1225 */
1226 if (pCreateInfo->samples > VK_SAMPLE_COUNT_1_BIT &&
1227 (usage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
1228 VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)))
1229 usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1230 return usage;
1231 }
1232
1233 static VkResult MUST_CHECK
alloc_private_binding(struct anv_device * device,struct anv_image * image,const VkImageCreateInfo * create_info)1234 alloc_private_binding(struct anv_device *device,
1235 struct anv_image *image,
1236 const VkImageCreateInfo *create_info)
1237 {
1238 struct anv_image_binding *binding =
1239 &image->bindings[ANV_IMAGE_MEMORY_BINDING_PRIVATE];
1240
1241 if (binding->memory_range.size == 0)
1242 return VK_SUCCESS;
1243
1244 const VkImageSwapchainCreateInfoKHR *swapchain_info =
1245 vk_find_struct_const(create_info->pNext, IMAGE_SWAPCHAIN_CREATE_INFO_KHR);
1246
1247 if (swapchain_info && swapchain_info->swapchain != VK_NULL_HANDLE) {
1248 /* The image will be bound to swapchain memory. */
1249 return VK_SUCCESS;
1250 }
1251
1252 return anv_device_alloc_bo(device, "image-binding-private",
1253 binding->memory_range.size, 0, 0,
1254 &binding->address.bo);
1255 }
1256
1257 VkResult
anv_image_init(struct anv_device * device,struct anv_image * image,const struct anv_image_create_info * create_info)1258 anv_image_init(struct anv_device *device, struct anv_image *image,
1259 const struct anv_image_create_info *create_info)
1260 {
1261 const VkImageCreateInfo *pCreateInfo = create_info->vk_info;
1262 const struct VkImageDrmFormatModifierExplicitCreateInfoEXT *mod_explicit_info = NULL;
1263 const struct isl_drm_modifier_info *isl_mod_info = NULL;
1264 VkResult r;
1265
1266 vk_image_init(&device->vk, &image->vk, pCreateInfo);
1267
1268 image->vk.usage = anv_image_create_usage(pCreateInfo, image->vk.usage);
1269 image->vk.stencil_usage =
1270 anv_image_create_usage(pCreateInfo, image->vk.stencil_usage);
1271
1272 if (pCreateInfo->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) {
1273 assert(!image->vk.wsi_legacy_scanout);
1274 mod_explicit_info =
1275 vk_find_struct_const(pCreateInfo->pNext,
1276 IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT);
1277 if (mod_explicit_info) {
1278 isl_mod_info = isl_drm_modifier_get_info(mod_explicit_info->drmFormatModifier);
1279 } else {
1280 const struct VkImageDrmFormatModifierListCreateInfoEXT *mod_list_info =
1281 vk_find_struct_const(pCreateInfo->pNext,
1282 IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT);
1283 isl_mod_info = choose_drm_format_mod(device->physical,
1284 mod_list_info->drmFormatModifierCount,
1285 mod_list_info->pDrmFormatModifiers);
1286 }
1287
1288 assert(isl_mod_info);
1289 assert(image->vk.drm_format_mod == DRM_FORMAT_MOD_INVALID);
1290 image->vk.drm_format_mod = isl_mod_info->modifier;
1291 }
1292
1293 for (int i = 0; i < ANV_IMAGE_MEMORY_BINDING_END; ++i) {
1294 image->bindings[i] = (struct anv_image_binding) {
1295 .memory_range = { .binding = i },
1296 };
1297 }
1298
1299 /* In case of AHardwareBuffer import, we don't know the layout yet */
1300 if (image->vk.external_handle_types &
1301 VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID) {
1302 image->from_ahb = true;
1303 return VK_SUCCESS;
1304 }
1305
1306 image->n_planes = anv_get_format_planes(image->vk.format);
1307
1308 /* The Vulkan 1.2.165 glossary says:
1309 *
1310 * A disjoint image consists of multiple disjoint planes, and is created
1311 * with the VK_IMAGE_CREATE_DISJOINT_BIT bit set.
1312 */
1313 image->disjoint = image->n_planes > 1 &&
1314 (pCreateInfo->flags & VK_IMAGE_CREATE_DISJOINT_BIT);
1315
1316 const isl_tiling_flags_t isl_tiling_flags =
1317 choose_isl_tiling_flags(&device->info, create_info, isl_mod_info,
1318 image->vk.wsi_legacy_scanout);
1319
1320 const VkImageFormatListCreateInfoKHR *fmt_list =
1321 vk_find_struct_const(pCreateInfo->pNext,
1322 IMAGE_FORMAT_LIST_CREATE_INFO_KHR);
1323
1324 if (mod_explicit_info) {
1325 r = add_all_surfaces_explicit_layout(device, image, fmt_list,
1326 mod_explicit_info, isl_tiling_flags,
1327 create_info->isl_extra_usage_flags);
1328 } else {
1329 r = add_all_surfaces_implicit_layout(device, image, fmt_list, 0,
1330 isl_tiling_flags,
1331 create_info);
1332 }
1333
1334 if (r != VK_SUCCESS)
1335 goto fail;
1336
1337 r = alloc_private_binding(device, image, pCreateInfo);
1338 if (r != VK_SUCCESS)
1339 goto fail;
1340
1341 check_memory_bindings(device, image);
1342
1343 r = check_drm_format_mod(device, image);
1344 if (r != VK_SUCCESS)
1345 goto fail;
1346
1347 return VK_SUCCESS;
1348
1349 fail:
1350 vk_image_finish(&image->vk);
1351 return r;
1352 }
1353
1354 void
anv_image_finish(struct anv_image * image)1355 anv_image_finish(struct anv_image *image)
1356 {
1357 struct anv_device *device =
1358 container_of(image->vk.base.device, struct anv_device, vk);
1359
1360 if (image->from_gralloc) {
1361 assert(!image->disjoint);
1362 assert(image->n_planes == 1);
1363 assert(image->planes[0].primary_surface.memory_range.binding ==
1364 ANV_IMAGE_MEMORY_BINDING_MAIN);
1365 assert(image->bindings[ANV_IMAGE_MEMORY_BINDING_MAIN].address.bo != NULL);
1366 anv_device_release_bo(device, image->bindings[ANV_IMAGE_MEMORY_BINDING_MAIN].address.bo);
1367 }
1368
1369 struct anv_bo *private_bo = image->bindings[ANV_IMAGE_MEMORY_BINDING_PRIVATE].address.bo;
1370 if (private_bo)
1371 anv_device_release_bo(device, private_bo);
1372
1373 vk_image_finish(&image->vk);
1374 }
1375
1376 static struct anv_image *
anv_swapchain_get_image(VkSwapchainKHR swapchain,uint32_t index)1377 anv_swapchain_get_image(VkSwapchainKHR swapchain,
1378 uint32_t index)
1379 {
1380 uint32_t n_images = index + 1;
1381 VkImage *images = malloc(sizeof(*images) * n_images);
1382 VkResult result = wsi_common_get_images(swapchain, &n_images, images);
1383
1384 if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
1385 free(images);
1386 return NULL;
1387 }
1388
1389 ANV_FROM_HANDLE(anv_image, image, images[index]);
1390 free(images);
1391
1392 return image;
1393 }
1394
1395 static VkResult
anv_image_init_from_swapchain(struct anv_device * device,struct anv_image * image,const VkImageCreateInfo * pCreateInfo,const VkImageSwapchainCreateInfoKHR * swapchain_info)1396 anv_image_init_from_swapchain(struct anv_device *device,
1397 struct anv_image *image,
1398 const VkImageCreateInfo *pCreateInfo,
1399 const VkImageSwapchainCreateInfoKHR *swapchain_info)
1400 {
1401 struct anv_image *swapchain_image = anv_swapchain_get_image(swapchain_info->swapchain, 0);
1402 assert(swapchain_image);
1403
1404 VkImageCreateInfo local_create_info = *pCreateInfo;
1405 local_create_info.pNext = NULL;
1406
1407 /* Added by wsi code. */
1408 local_create_info.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
1409
1410 /* The spec requires TILING_OPTIMAL as input, but the swapchain image may
1411 * privately use a different tiling. See spec anchor
1412 * #swapchain-wsi-image-create-info .
1413 */
1414 assert(local_create_info.tiling == VK_IMAGE_TILING_OPTIMAL);
1415 local_create_info.tiling = swapchain_image->vk.tiling;
1416
1417 VkImageDrmFormatModifierListCreateInfoEXT local_modifier_info = {
1418 .sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT,
1419 .drmFormatModifierCount = 1,
1420 .pDrmFormatModifiers = &swapchain_image->vk.drm_format_mod,
1421 };
1422
1423 if (swapchain_image->vk.drm_format_mod != DRM_FORMAT_MOD_INVALID)
1424 __vk_append_struct(&local_create_info, &local_modifier_info);
1425
1426 assert(swapchain_image->vk.image_type == local_create_info.imageType);
1427 assert(swapchain_image->vk.format == local_create_info.format);
1428 assert(swapchain_image->vk.extent.width == local_create_info.extent.width);
1429 assert(swapchain_image->vk.extent.height == local_create_info.extent.height);
1430 assert(swapchain_image->vk.extent.depth == local_create_info.extent.depth);
1431 assert(swapchain_image->vk.array_layers == local_create_info.arrayLayers);
1432 assert(swapchain_image->vk.samples == local_create_info.samples);
1433 assert(swapchain_image->vk.tiling == local_create_info.tiling);
1434 assert(swapchain_image->vk.usage == local_create_info.usage);
1435
1436 return anv_image_init(device, image,
1437 &(struct anv_image_create_info) {
1438 .vk_info = &local_create_info,
1439 });
1440 }
1441
1442 static VkResult
anv_image_init_from_create_info(struct anv_device * device,struct anv_image * image,const VkImageCreateInfo * pCreateInfo)1443 anv_image_init_from_create_info(struct anv_device *device,
1444 struct anv_image *image,
1445 const VkImageCreateInfo *pCreateInfo)
1446 {
1447 const VkNativeBufferANDROID *gralloc_info =
1448 vk_find_struct_const(pCreateInfo->pNext, NATIVE_BUFFER_ANDROID);
1449 if (gralloc_info)
1450 return anv_image_init_from_gralloc(device, image, pCreateInfo,
1451 gralloc_info);
1452
1453 #ifndef VK_USE_PLATFORM_ANDROID_KHR
1454 /* Ignore swapchain creation info on Android. Since we don't have an
1455 * implementation in Mesa, we're guaranteed to access an Android object
1456 * incorrectly.
1457 */
1458 const VkImageSwapchainCreateInfoKHR *swapchain_info =
1459 vk_find_struct_const(pCreateInfo->pNext, IMAGE_SWAPCHAIN_CREATE_INFO_KHR);
1460 if (swapchain_info && swapchain_info->swapchain != VK_NULL_HANDLE) {
1461 return anv_image_init_from_swapchain(device, image, pCreateInfo,
1462 swapchain_info);
1463 }
1464 #endif
1465
1466 return anv_image_init(device, image,
1467 &(struct anv_image_create_info) {
1468 .vk_info = pCreateInfo,
1469 });
1470 }
1471
anv_CreateImage(VkDevice _device,const VkImageCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkImage * pImage)1472 VkResult anv_CreateImage(
1473 VkDevice _device,
1474 const VkImageCreateInfo* pCreateInfo,
1475 const VkAllocationCallbacks* pAllocator,
1476 VkImage* pImage)
1477 {
1478 ANV_FROM_HANDLE(anv_device, device, _device);
1479
1480 struct anv_image *image =
1481 vk_object_zalloc(&device->vk, pAllocator, sizeof(*image),
1482 VK_OBJECT_TYPE_IMAGE);
1483 if (!image)
1484 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
1485
1486 VkResult result = anv_image_init_from_create_info(device, image,
1487 pCreateInfo);
1488 if (result != VK_SUCCESS) {
1489 vk_object_free(&device->vk, pAllocator, image);
1490 return result;
1491 }
1492
1493 *pImage = anv_image_to_handle(image);
1494
1495 return result;
1496 }
1497
1498 void
anv_DestroyImage(VkDevice _device,VkImage _image,const VkAllocationCallbacks * pAllocator)1499 anv_DestroyImage(VkDevice _device, VkImage _image,
1500 const VkAllocationCallbacks *pAllocator)
1501 {
1502 ANV_FROM_HANDLE(anv_device, device, _device);
1503 ANV_FROM_HANDLE(anv_image, image, _image);
1504
1505 if (!image)
1506 return;
1507
1508 assert(&device->vk == image->vk.base.device);
1509 anv_image_finish(image);
1510
1511 vk_free2(&device->vk.alloc, pAllocator, image);
1512 }
1513
1514 /* We are binding AHardwareBuffer. Get a description, resolve the
1515 * format and prepare anv_image properly.
1516 */
1517 static void
resolve_ahw_image(struct anv_device * device,struct anv_image * image,struct anv_device_memory * mem)1518 resolve_ahw_image(struct anv_device *device,
1519 struct anv_image *image,
1520 struct anv_device_memory *mem)
1521 {
1522 #if defined(ANDROID) && ANDROID_API_LEVEL >= 26
1523 assert(mem->ahw);
1524 AHardwareBuffer_Desc desc;
1525 AHardwareBuffer_describe(mem->ahw, &desc);
1526 VkResult result;
1527
1528 /* Check tiling. */
1529 int i915_tiling = anv_gem_get_tiling(device, mem->bo->gem_handle);
1530 VkImageTiling vk_tiling;
1531 isl_tiling_flags_t isl_tiling_flags = 0;
1532
1533 switch (i915_tiling) {
1534 case I915_TILING_NONE:
1535 vk_tiling = VK_IMAGE_TILING_LINEAR;
1536 isl_tiling_flags = ISL_TILING_LINEAR_BIT;
1537 break;
1538 case I915_TILING_X:
1539 vk_tiling = VK_IMAGE_TILING_OPTIMAL;
1540 isl_tiling_flags = ISL_TILING_X_BIT;
1541 break;
1542 case I915_TILING_Y:
1543 vk_tiling = VK_IMAGE_TILING_OPTIMAL;
1544 isl_tiling_flags = ISL_TILING_Y0_BIT;
1545 break;
1546 case -1:
1547 default:
1548 unreachable("Invalid tiling flags.");
1549 }
1550
1551 assert(vk_tiling == VK_IMAGE_TILING_LINEAR ||
1552 vk_tiling == VK_IMAGE_TILING_OPTIMAL);
1553
1554 /* Check format. */
1555 VkFormat vk_format = vk_format_from_android(desc.format, desc.usage);
1556 enum isl_format isl_fmt = anv_get_isl_format(&device->info,
1557 vk_format,
1558 VK_IMAGE_ASPECT_COLOR_BIT,
1559 vk_tiling);
1560 assert(isl_fmt != ISL_FORMAT_UNSUPPORTED);
1561
1562 /* Handle RGB(X)->RGBA fallback. */
1563 switch (desc.format) {
1564 case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
1565 case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
1566 if (isl_format_is_rgb(isl_fmt))
1567 isl_fmt = isl_format_rgb_to_rgba(isl_fmt);
1568 break;
1569 }
1570
1571 /* Now we are able to fill anv_image fields properly and create
1572 * isl_surface for it.
1573 */
1574 vk_image_set_format(&image->vk, vk_format);
1575 image->n_planes = anv_get_format_planes(image->vk.format);
1576
1577 uint32_t stride = desc.stride *
1578 (isl_format_get_layout(isl_fmt)->bpb / 8);
1579
1580 struct anv_image_create_info create_info = {
1581 .isl_extra_usage_flags = ISL_SURF_USAGE_DISABLE_AUX_BIT,
1582 };
1583
1584 result = add_all_surfaces_implicit_layout(device, image, NULL, stride,
1585 isl_tiling_flags,
1586 &create_info);
1587 assert(result == VK_SUCCESS);
1588 #endif
1589 }
1590
1591 void
anv_image_get_memory_requirements(struct anv_device * device,struct anv_image * image,VkImageAspectFlags aspects,VkMemoryRequirements2 * pMemoryRequirements)1592 anv_image_get_memory_requirements(struct anv_device *device,
1593 struct anv_image *image,
1594 VkImageAspectFlags aspects,
1595 VkMemoryRequirements2 *pMemoryRequirements)
1596 {
1597 /* The Vulkan spec (git aaed022) says:
1598 *
1599 * memoryTypeBits is a bitfield and contains one bit set for every
1600 * supported memory type for the resource. The bit `1<<i` is set if and
1601 * only if the memory type `i` in the VkPhysicalDeviceMemoryProperties
1602 * structure for the physical device is supported.
1603 *
1604 * All types are currently supported for images.
1605 */
1606 uint32_t memory_types = (1ull << device->physical->memory.type_count) - 1;
1607
1608 vk_foreach_struct(ext, pMemoryRequirements->pNext) {
1609 switch (ext->sType) {
1610 case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: {
1611 VkMemoryDedicatedRequirements *requirements = (void *)ext;
1612 if (image->vk.wsi_legacy_scanout || image->from_ahb) {
1613 /* If we need to set the tiling for external consumers, we need a
1614 * dedicated allocation.
1615 *
1616 * See also anv_AllocateMemory.
1617 */
1618 requirements->prefersDedicatedAllocation = true;
1619 requirements->requiresDedicatedAllocation = true;
1620 } else {
1621 requirements->prefersDedicatedAllocation = false;
1622 requirements->requiresDedicatedAllocation = false;
1623 }
1624 break;
1625 }
1626
1627 default:
1628 anv_debug_ignored_stype(ext->sType);
1629 break;
1630 }
1631 }
1632
1633 /* If the image is disjoint, then we must return the memory requirements for
1634 * the single plane specified in VkImagePlaneMemoryRequirementsInfo. If
1635 * non-disjoint, then exactly one set of memory requirements exists for the
1636 * whole image.
1637 *
1638 * This is enforced by the Valid Usage for VkImageMemoryRequirementsInfo2,
1639 * which requires that the app provide VkImagePlaneMemoryRequirementsInfo if
1640 * and only if the image is disjoint (that is, multi-planar format and
1641 * VK_IMAGE_CREATE_DISJOINT_BIT).
1642 */
1643 const struct anv_image_binding *binding;
1644 if (image->disjoint) {
1645 assert(util_bitcount(aspects) == 1);
1646 assert(aspects & image->vk.aspects);
1647 binding = image_aspect_to_binding(image, aspects);
1648 } else {
1649 assert(aspects == image->vk.aspects);
1650 binding = &image->bindings[ANV_IMAGE_MEMORY_BINDING_MAIN];
1651 }
1652
1653 pMemoryRequirements->memoryRequirements = (VkMemoryRequirements) {
1654 .size = binding->memory_range.size,
1655 .alignment = binding->memory_range.alignment,
1656 .memoryTypeBits = memory_types,
1657 };
1658 }
1659
anv_GetImageMemoryRequirements2(VkDevice _device,const VkImageMemoryRequirementsInfo2 * pInfo,VkMemoryRequirements2 * pMemoryRequirements)1660 void anv_GetImageMemoryRequirements2(
1661 VkDevice _device,
1662 const VkImageMemoryRequirementsInfo2* pInfo,
1663 VkMemoryRequirements2* pMemoryRequirements)
1664 {
1665 ANV_FROM_HANDLE(anv_device, device, _device);
1666 ANV_FROM_HANDLE(anv_image, image, pInfo->image);
1667
1668 VkImageAspectFlags aspects = image->vk.aspects;
1669
1670 vk_foreach_struct_const(ext, pInfo->pNext) {
1671 switch (ext->sType) {
1672 case VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO: {
1673 assert(image->disjoint);
1674 const VkImagePlaneMemoryRequirementsInfo *plane_reqs =
1675 (const VkImagePlaneMemoryRequirementsInfo *) ext;
1676 aspects = plane_reqs->planeAspect;
1677 break;
1678 }
1679
1680 default:
1681 anv_debug_ignored_stype(ext->sType);
1682 break;
1683 }
1684 }
1685
1686 anv_image_get_memory_requirements(device, image, aspects,
1687 pMemoryRequirements);
1688 }
1689
anv_GetDeviceImageMemoryRequirementsKHR(VkDevice _device,const VkDeviceImageMemoryRequirementsKHR * pInfo,VkMemoryRequirements2 * pMemoryRequirements)1690 void anv_GetDeviceImageMemoryRequirementsKHR(
1691 VkDevice _device,
1692 const VkDeviceImageMemoryRequirementsKHR* pInfo,
1693 VkMemoryRequirements2* pMemoryRequirements)
1694 {
1695 ANV_FROM_HANDLE(anv_device, device, _device);
1696 struct anv_image image = { 0 };
1697
1698 ASSERTED VkResult result =
1699 anv_image_init_from_create_info(device, &image, pInfo->pCreateInfo);
1700 assert(result == VK_SUCCESS);
1701
1702 VkImageAspectFlags aspects =
1703 image.disjoint ? pInfo->planeAspect : image.vk.aspects;
1704
1705 anv_image_get_memory_requirements(device, &image, aspects,
1706 pMemoryRequirements);
1707 }
1708
anv_GetImageSparseMemoryRequirements(VkDevice device,VkImage image,uint32_t * pSparseMemoryRequirementCount,VkSparseImageMemoryRequirements * pSparseMemoryRequirements)1709 void anv_GetImageSparseMemoryRequirements(
1710 VkDevice device,
1711 VkImage image,
1712 uint32_t* pSparseMemoryRequirementCount,
1713 VkSparseImageMemoryRequirements* pSparseMemoryRequirements)
1714 {
1715 *pSparseMemoryRequirementCount = 0;
1716 }
1717
anv_GetImageSparseMemoryRequirements2(VkDevice device,const VkImageSparseMemoryRequirementsInfo2 * pInfo,uint32_t * pSparseMemoryRequirementCount,VkSparseImageMemoryRequirements2 * pSparseMemoryRequirements)1718 void anv_GetImageSparseMemoryRequirements2(
1719 VkDevice device,
1720 const VkImageSparseMemoryRequirementsInfo2* pInfo,
1721 uint32_t* pSparseMemoryRequirementCount,
1722 VkSparseImageMemoryRequirements2* pSparseMemoryRequirements)
1723 {
1724 *pSparseMemoryRequirementCount = 0;
1725 }
1726
anv_GetDeviceImageSparseMemoryRequirementsKHR(VkDevice device,const VkDeviceImageMemoryRequirementsKHR * pInfo,uint32_t * pSparseMemoryRequirementCount,VkSparseImageMemoryRequirements2 * pSparseMemoryRequirements)1727 void anv_GetDeviceImageSparseMemoryRequirementsKHR(
1728 VkDevice device,
1729 const VkDeviceImageMemoryRequirementsKHR* pInfo,
1730 uint32_t* pSparseMemoryRequirementCount,
1731 VkSparseImageMemoryRequirements2* pSparseMemoryRequirements)
1732 {
1733 *pSparseMemoryRequirementCount = 0;
1734 }
1735
anv_BindImageMemory2(VkDevice _device,uint32_t bindInfoCount,const VkBindImageMemoryInfo * pBindInfos)1736 VkResult anv_BindImageMemory2(
1737 VkDevice _device,
1738 uint32_t bindInfoCount,
1739 const VkBindImageMemoryInfo* pBindInfos)
1740 {
1741 ANV_FROM_HANDLE(anv_device, device, _device);
1742
1743 for (uint32_t i = 0; i < bindInfoCount; i++) {
1744 const VkBindImageMemoryInfo *bind_info = &pBindInfos[i];
1745 ANV_FROM_HANDLE(anv_device_memory, mem, bind_info->memory);
1746 ANV_FROM_HANDLE(anv_image, image, bind_info->image);
1747 bool did_bind = false;
1748
1749 /* Resolve will alter the image's aspects, do this first. */
1750 if (mem && mem->ahw)
1751 resolve_ahw_image(device, image, mem);
1752
1753 vk_foreach_struct_const(s, bind_info->pNext) {
1754 switch (s->sType) {
1755 case VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO: {
1756 const VkBindImagePlaneMemoryInfo *plane_info =
1757 (const VkBindImagePlaneMemoryInfo *) s;
1758
1759 /* Workaround for possible spec bug.
1760 *
1761 * Unlike VkImagePlaneMemoryRequirementsInfo, which requires that
1762 * the image be disjoint (that is, multi-planar format and
1763 * VK_IMAGE_CREATE_DISJOINT_BIT), VkBindImagePlaneMemoryInfo allows
1764 * the image to be non-disjoint and requires only that the image
1765 * have the DISJOINT flag. In this case, regardless of the value of
1766 * VkImagePlaneMemoryRequirementsInfo::planeAspect, the behavior is
1767 * the same as if VkImagePlaneMemoryRequirementsInfo were omitted.
1768 */
1769 if (!image->disjoint)
1770 break;
1771
1772 struct anv_image_binding *binding =
1773 image_aspect_to_binding(image, plane_info->planeAspect);
1774
1775 binding->address = (struct anv_address) {
1776 .bo = mem->bo,
1777 .offset = bind_info->memoryOffset,
1778 };
1779
1780 did_bind = true;
1781 break;
1782 }
1783 case VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR: {
1784 /* Ignore this struct on Android, we cannot access swapchain
1785 * structures threre.
1786 */
1787 #ifndef VK_USE_PLATFORM_ANDROID_KHR
1788 const VkBindImageMemorySwapchainInfoKHR *swapchain_info =
1789 (const VkBindImageMemorySwapchainInfoKHR *) s;
1790 struct anv_image *swapchain_image =
1791 anv_swapchain_get_image(swapchain_info->swapchain,
1792 swapchain_info->imageIndex);
1793 assert(swapchain_image);
1794 assert(image->vk.aspects == swapchain_image->vk.aspects);
1795 assert(mem == NULL);
1796
1797 for (int j = 0; j < ARRAY_SIZE(image->bindings); ++j)
1798 image->bindings[j].address = swapchain_image->bindings[j].address;
1799
1800 /* We must bump the private binding's bo's refcount because, unlike the other
1801 * bindings, its lifetime is not application-managed.
1802 */
1803 struct anv_bo *private_bo =
1804 image->bindings[ANV_IMAGE_MEMORY_BINDING_PRIVATE].address.bo;
1805 if (private_bo)
1806 anv_bo_ref(private_bo);
1807
1808 did_bind = true;
1809 #endif
1810 break;
1811 }
1812 #pragma GCC diagnostic push
1813 #pragma GCC diagnostic ignored "-Wswitch"
1814 case VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID: {
1815 const VkNativeBufferANDROID *gralloc_info =
1816 (const VkNativeBufferANDROID *)s;
1817 VkResult result = anv_image_bind_from_gralloc(device, image,
1818 gralloc_info);
1819 if (result != VK_SUCCESS)
1820 return result;
1821 did_bind = true;
1822 break;
1823 }
1824 #pragma GCC diagnostic pop
1825 default:
1826 anv_debug_ignored_stype(s->sType);
1827 break;
1828 }
1829 }
1830
1831 if (!did_bind) {
1832 assert(!image->disjoint);
1833
1834 image->bindings[ANV_IMAGE_MEMORY_BINDING_MAIN].address =
1835 (struct anv_address) {
1836 .bo = mem->bo,
1837 .offset = bind_info->memoryOffset,
1838 };
1839
1840 did_bind = true;
1841 }
1842
1843 /* On platforms that use implicit CCS, if the plane's bo lacks implicit
1844 * CCS then disable compression on the plane.
1845 */
1846 for (int p = 0; p < image->n_planes; ++p) {
1847 enum anv_image_memory_binding binding =
1848 image->planes[p].primary_surface.memory_range.binding;
1849 const struct anv_bo *bo =
1850 image->bindings[binding].address.bo;
1851
1852 if (bo && !bo->has_implicit_ccs &&
1853 device->physical->has_implicit_ccs)
1854 image->planes[p].aux_usage = ISL_AUX_USAGE_NONE;
1855 }
1856 }
1857
1858 return VK_SUCCESS;
1859 }
1860
anv_GetImageSubresourceLayout(VkDevice device,VkImage _image,const VkImageSubresource * subresource,VkSubresourceLayout * layout)1861 void anv_GetImageSubresourceLayout(
1862 VkDevice device,
1863 VkImage _image,
1864 const VkImageSubresource* subresource,
1865 VkSubresourceLayout* layout)
1866 {
1867 ANV_FROM_HANDLE(anv_image, image, _image);
1868 const struct anv_surface *surface;
1869
1870 assert(__builtin_popcount(subresource->aspectMask) == 1);
1871
1872 /* The Vulkan spec requires that aspectMask be
1873 * VK_IMAGE_ASPECT_MEMORY_PLANE_i_BIT_EXT if tiling is
1874 * VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT.
1875 *
1876 * For swapchain images, the Vulkan spec says that every swapchain image has
1877 * tiling VK_IMAGE_TILING_OPTIMAL, but we may choose
1878 * VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT internally. Vulkan doesn't allow
1879 * vkGetImageSubresourceLayout for images with VK_IMAGE_TILING_OPTIMAL,
1880 * therefore it's invalid for the application to call this on a swapchain
1881 * image. The WSI code, however, knows when it has internally created
1882 * a swapchain image with VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT,
1883 * so it _should_ correctly use VK_IMAGE_ASPECT_MEMORY_PLANE_* in that case.
1884 * But it incorrectly uses VK_IMAGE_ASPECT_PLANE_*, so we have a temporary
1885 * workaround.
1886 */
1887 if (image->vk.tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) {
1888 /* TODO(chadv): Drop this workaround when WSI gets fixed. */
1889 uint32_t mem_plane;
1890 switch (subresource->aspectMask) {
1891 case VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT:
1892 case VK_IMAGE_ASPECT_PLANE_0_BIT:
1893 mem_plane = 0;
1894 break;
1895 case VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT:
1896 case VK_IMAGE_ASPECT_PLANE_1_BIT:
1897 mem_plane = 1;
1898 break;
1899 case VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT:
1900 case VK_IMAGE_ASPECT_PLANE_2_BIT:
1901 mem_plane = 2;
1902 break;
1903 default:
1904 unreachable("bad VkImageAspectFlags");
1905 }
1906
1907 if (mem_plane == 1 && isl_drm_modifier_has_aux(image->vk.drm_format_mod)) {
1908 assert(image->n_planes == 1);
1909 /* If the memory binding differs between primary and aux, then the
1910 * returned offset will be incorrect.
1911 */
1912 assert(image->planes[0].aux_surface.memory_range.binding ==
1913 image->planes[0].primary_surface.memory_range.binding);
1914 surface = &image->planes[0].aux_surface;
1915 } else {
1916 assert(mem_plane < image->n_planes);
1917 surface = &image->planes[mem_plane].primary_surface;
1918 }
1919 } else {
1920 const uint32_t plane =
1921 anv_image_aspect_to_plane(image, subresource->aspectMask);
1922 surface = &image->planes[plane].primary_surface;
1923 }
1924
1925 layout->offset = surface->memory_range.offset;
1926 layout->rowPitch = surface->isl.row_pitch_B;
1927 layout->depthPitch = isl_surf_get_array_pitch(&surface->isl);
1928 layout->arrayPitch = isl_surf_get_array_pitch(&surface->isl);
1929
1930 if (subresource->mipLevel > 0 || subresource->arrayLayer > 0) {
1931 assert(surface->isl.tiling == ISL_TILING_LINEAR);
1932
1933 uint64_t offset_B;
1934 isl_surf_get_image_offset_B_tile_sa(&surface->isl,
1935 subresource->mipLevel,
1936 subresource->arrayLayer,
1937 0 /* logical_z_offset_px */,
1938 &offset_B, NULL, NULL);
1939 layout->offset += offset_B;
1940 layout->size = layout->rowPitch * anv_minify(image->vk.extent.height,
1941 subresource->mipLevel) *
1942 image->vk.extent.depth;
1943 } else {
1944 layout->size = surface->memory_range.size;
1945 }
1946 }
1947
1948 /**
1949 * This function returns the assumed isl_aux_state for a given VkImageLayout.
1950 * Because Vulkan image layouts don't map directly to isl_aux_state enums, the
1951 * returned enum is the assumed worst case.
1952 *
1953 * @param devinfo The device information of the Intel GPU.
1954 * @param image The image that may contain a collection of buffers.
1955 * @param aspect The aspect of the image to be accessed.
1956 * @param layout The current layout of the image aspect(s).
1957 *
1958 * @return The primary buffer that should be used for the given layout.
1959 */
1960 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)1961 anv_layout_to_aux_state(const struct intel_device_info * const devinfo,
1962 const struct anv_image * const image,
1963 const VkImageAspectFlagBits aspect,
1964 const VkImageLayout layout)
1965 {
1966 /* Validate the inputs. */
1967
1968 /* The devinfo is needed as the optimal buffer varies across generations. */
1969 assert(devinfo != NULL);
1970
1971 /* The layout of a NULL image is not properly defined. */
1972 assert(image != NULL);
1973
1974 /* The aspect must be exactly one of the image aspects. */
1975 assert(util_bitcount(aspect) == 1 && (aspect & image->vk.aspects));
1976
1977 /* Determine the optimal buffer. */
1978
1979 const uint32_t plane = anv_image_aspect_to_plane(image, aspect);
1980
1981 /* If we don't have an aux buffer then aux state makes no sense */
1982 const enum isl_aux_usage aux_usage = image->planes[plane].aux_usage;
1983 assert(aux_usage != ISL_AUX_USAGE_NONE);
1984
1985 /* All images that use an auxiliary surface are required to be tiled. */
1986 assert(image->planes[plane].primary_surface.isl.tiling != ISL_TILING_LINEAR);
1987
1988 /* Handle a few special cases */
1989 switch (layout) {
1990 /* Invalid layouts */
1991 case VK_IMAGE_LAYOUT_MAX_ENUM:
1992 unreachable("Invalid image layout.");
1993
1994 /* Undefined layouts
1995 *
1996 * The pre-initialized layout is equivalent to the undefined layout for
1997 * optimally-tiled images. We can only do color compression (CCS or HiZ)
1998 * on tiled images.
1999 */
2000 case VK_IMAGE_LAYOUT_UNDEFINED:
2001 case VK_IMAGE_LAYOUT_PREINITIALIZED:
2002 return ISL_AUX_STATE_AUX_INVALID;
2003
2004 case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR: {
2005 assert(image->vk.aspects == VK_IMAGE_ASPECT_COLOR_BIT);
2006
2007 enum isl_aux_state aux_state =
2008 isl_drm_modifier_get_default_aux_state(image->vk.drm_format_mod);
2009
2010 switch (aux_state) {
2011 default:
2012 assert(!"unexpected isl_aux_state");
2013 case ISL_AUX_STATE_AUX_INVALID:
2014 /* The modifier does not support compression. But, if we arrived
2015 * here, then we have enabled compression on it anyway, in which case
2016 * we must resolve the aux surface before we release ownership to the
2017 * presentation engine (because, having no modifier, the presentation
2018 * engine will not be aware of the aux surface). The presentation
2019 * engine will not access the aux surface (because it is unware of
2020 * it), and so the aux surface will still be resolved when we
2021 * re-acquire ownership.
2022 *
2023 * Therefore, at ownership transfers in either direction, there does
2024 * exist an aux surface despite the lack of modifier and its state is
2025 * pass-through.
2026 */
2027 return ISL_AUX_STATE_PASS_THROUGH;
2028 case ISL_AUX_STATE_COMPRESSED_NO_CLEAR:
2029 return ISL_AUX_STATE_COMPRESSED_NO_CLEAR;
2030 }
2031 }
2032
2033 default:
2034 break;
2035 }
2036
2037 const bool read_only = vk_image_layout_is_read_only(layout, aspect);
2038
2039 const VkImageUsageFlags image_aspect_usage =
2040 vk_image_usage(&image->vk, aspect);
2041 const VkImageUsageFlags usage =
2042 vk_image_layout_to_usage_flags(layout, aspect) & image_aspect_usage;
2043
2044 bool aux_supported = true;
2045 bool clear_supported = isl_aux_usage_has_fast_clears(aux_usage);
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 (layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) {
2269 /* When we're in a render pass we have the clear color data from the
2270 * VkRenderPassBeginInfo and we can use arbitrary clear colors. They
2271 * must get partially resolved before we leave the render pass.
2272 */
2273 return ANV_FAST_CLEAR_ANY;
2274 } else if (image->planes[plane].aux_usage == ISL_AUX_USAGE_MCS ||
2275 image->planes[plane].aux_usage == ISL_AUX_USAGE_CCS_E) {
2276 if (devinfo->ver >= 11) {
2277 /* On ICL and later, the sampler hardware uses a copy of the clear
2278 * value that is encoded as a pixel value. Therefore, we can use
2279 * any clear color we like for sampling.
2280 */
2281 return ANV_FAST_CLEAR_ANY;
2282 } else {
2283 /* If the image has MCS or CCS_E enabled all the time then we can
2284 * use fast-clear as long as the clear color is the default value
2285 * of zero since this is the default value we program into every
2286 * surface state used for texturing.
2287 */
2288 return ANV_FAST_CLEAR_DEFAULT_VALUE;
2289 }
2290 } else {
2291 return ANV_FAST_CLEAR_NONE;
2292 }
2293
2294 case ISL_AUX_STATE_COMPRESSED_NO_CLEAR:
2295 case ISL_AUX_STATE_RESOLVED:
2296 case ISL_AUX_STATE_PASS_THROUGH:
2297 case ISL_AUX_STATE_AUX_INVALID:
2298 return ANV_FAST_CLEAR_NONE;
2299 }
2300
2301 unreachable("Invalid isl_aux_state");
2302 }
2303
2304
2305 static struct anv_state
alloc_surface_state(struct anv_device * device)2306 alloc_surface_state(struct anv_device *device)
2307 {
2308 return anv_state_pool_alloc(&device->surface_state_pool, 64, 64);
2309 }
2310
2311 static enum isl_channel_select
remap_swizzle(VkComponentSwizzle swizzle,struct isl_swizzle format_swizzle)2312 remap_swizzle(VkComponentSwizzle swizzle,
2313 struct isl_swizzle format_swizzle)
2314 {
2315 switch (swizzle) {
2316 case VK_COMPONENT_SWIZZLE_ZERO: return ISL_CHANNEL_SELECT_ZERO;
2317 case VK_COMPONENT_SWIZZLE_ONE: return ISL_CHANNEL_SELECT_ONE;
2318 case VK_COMPONENT_SWIZZLE_R: return format_swizzle.r;
2319 case VK_COMPONENT_SWIZZLE_G: return format_swizzle.g;
2320 case VK_COMPONENT_SWIZZLE_B: return format_swizzle.b;
2321 case VK_COMPONENT_SWIZZLE_A: return format_swizzle.a;
2322 default:
2323 unreachable("Invalid swizzle");
2324 }
2325 }
2326
2327 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)2328 anv_image_fill_surface_state(struct anv_device *device,
2329 const struct anv_image *image,
2330 VkImageAspectFlagBits aspect,
2331 const struct isl_view *view_in,
2332 isl_surf_usage_flags_t view_usage,
2333 enum isl_aux_usage aux_usage,
2334 const union isl_color_value *clear_color,
2335 enum anv_image_view_state_flags flags,
2336 struct anv_surface_state *state_inout,
2337 struct brw_image_param *image_param_out)
2338 {
2339 const uint32_t plane = anv_image_aspect_to_plane(image, aspect);
2340
2341 const struct anv_surface *surface = &image->planes[plane].primary_surface,
2342 *aux_surface = &image->planes[plane].aux_surface;
2343
2344 struct isl_view view = *view_in;
2345 view.usage |= view_usage;
2346
2347 /* For texturing with VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL from a
2348 * compressed surface with a shadow surface, we use the shadow instead of
2349 * the primary surface. The shadow surface will be tiled, unlike the main
2350 * surface, so it should get significantly better performance.
2351 */
2352 if (anv_surface_is_valid(&image->planes[plane].shadow_surface) &&
2353 isl_format_is_compressed(view.format) &&
2354 (flags & ANV_IMAGE_VIEW_STATE_TEXTURE_OPTIMAL)) {
2355 assert(isl_format_is_compressed(surface->isl.format));
2356 assert(surface->isl.tiling == ISL_TILING_LINEAR);
2357 assert(image->planes[plane].shadow_surface.isl.tiling != ISL_TILING_LINEAR);
2358 surface = &image->planes[plane].shadow_surface;
2359 }
2360
2361 /* For texturing from stencil on gfx7, we have to sample from a shadow
2362 * surface because we don't support W-tiling in the sampler.
2363 */
2364 if (anv_surface_is_valid(&image->planes[plane].shadow_surface) &&
2365 aspect == VK_IMAGE_ASPECT_STENCIL_BIT) {
2366 assert(device->info.ver == 7);
2367 assert(view_usage & ISL_SURF_USAGE_TEXTURE_BIT);
2368 surface = &image->planes[plane].shadow_surface;
2369 }
2370
2371 if (view_usage == ISL_SURF_USAGE_RENDER_TARGET_BIT)
2372 view.swizzle = anv_swizzle_for_render(view.swizzle);
2373
2374 /* On Ivy Bridge and Bay Trail we do the swizzle in the shader */
2375 if (device->info.verx10 == 70)
2376 view.swizzle = ISL_SWIZZLE_IDENTITY;
2377
2378 /* If this is a HiZ buffer we can sample from with a programmable clear
2379 * value (SKL+), define the clear value to the optimal constant.
2380 */
2381 union isl_color_value default_clear_color = { .u32 = { 0, } };
2382 if (device->info.ver >= 9 && aspect == VK_IMAGE_ASPECT_DEPTH_BIT)
2383 default_clear_color.f32[0] = ANV_HZ_FC_VAL;
2384 if (!clear_color)
2385 clear_color = &default_clear_color;
2386
2387 const struct anv_address address =
2388 anv_image_address(image, &surface->memory_range);
2389
2390 if (view_usage == ISL_SURF_USAGE_STORAGE_BIT &&
2391 (flags & ANV_IMAGE_VIEW_STATE_STORAGE_LOWERED) &&
2392 !isl_has_matching_typed_storage_image_format(&device->info,
2393 view.format)) {
2394 /* In this case, we are a writeable storage buffer which needs to be
2395 * lowered to linear. All tiling and offset calculations will be done in
2396 * the shader.
2397 */
2398 assert(aux_usage == ISL_AUX_USAGE_NONE);
2399 isl_buffer_fill_state(&device->isl_dev, state_inout->state.map,
2400 .address = anv_address_physical(address),
2401 .size_B = surface->isl.size_B,
2402 .format = ISL_FORMAT_RAW,
2403 .swizzle = ISL_SWIZZLE_IDENTITY,
2404 .stride_B = 1,
2405 .mocs = anv_mocs(device, address.bo, view_usage));
2406 state_inout->address = address,
2407 state_inout->aux_address = ANV_NULL_ADDRESS;
2408 state_inout->clear_address = ANV_NULL_ADDRESS;
2409 } else {
2410 if (view_usage == ISL_SURF_USAGE_STORAGE_BIT &&
2411 (flags & ANV_IMAGE_VIEW_STATE_STORAGE_LOWERED)) {
2412 /* Typed surface reads support a very limited subset of the shader
2413 * image formats. Translate it into the closest format the hardware
2414 * supports.
2415 */
2416 assert(aux_usage == ISL_AUX_USAGE_NONE);
2417 view.format = isl_lower_storage_image_format(&device->info,
2418 view.format);
2419 }
2420
2421 const struct isl_surf *isl_surf = &surface->isl;
2422
2423 struct isl_surf tmp_surf;
2424 uint64_t offset_B = 0;
2425 uint32_t tile_x_sa = 0, tile_y_sa = 0;
2426 if (isl_format_is_compressed(surface->isl.format) &&
2427 !isl_format_is_compressed(view.format)) {
2428 /* We're creating an uncompressed view of a compressed surface. This
2429 * is allowed but only for a single level/layer.
2430 */
2431 assert(surface->isl.samples == 1);
2432 assert(view.levels == 1);
2433 assert(view.array_len == 1);
2434
2435 ASSERTED bool ok =
2436 isl_surf_get_uncompressed_surf(&device->isl_dev, isl_surf, &view,
2437 &tmp_surf, &view,
2438 &offset_B, &tile_x_sa, &tile_y_sa);
2439 assert(ok);
2440 isl_surf = &tmp_surf;
2441
2442 if (device->info.ver <= 8) {
2443 assert(surface->isl.tiling == ISL_TILING_LINEAR);
2444 assert(tile_x_sa == 0);
2445 assert(tile_y_sa == 0);
2446 }
2447 }
2448
2449 state_inout->address = anv_address_add(address, offset_B);
2450
2451 struct anv_address aux_address = ANV_NULL_ADDRESS;
2452 if (aux_usage != ISL_AUX_USAGE_NONE)
2453 aux_address = anv_image_address(image, &aux_surface->memory_range);
2454 state_inout->aux_address = aux_address;
2455
2456 struct anv_address clear_address = ANV_NULL_ADDRESS;
2457 if (device->info.ver >= 10 && isl_aux_usage_has_fast_clears(aux_usage)) {
2458 clear_address = anv_image_get_clear_color_addr(device, image, aspect);
2459 }
2460 state_inout->clear_address = clear_address;
2461
2462 isl_surf_fill_state(&device->isl_dev, state_inout->state.map,
2463 .surf = isl_surf,
2464 .view = &view,
2465 .address = anv_address_physical(state_inout->address),
2466 .clear_color = *clear_color,
2467 .aux_surf = &aux_surface->isl,
2468 .aux_usage = aux_usage,
2469 .aux_address = anv_address_physical(aux_address),
2470 .clear_address = anv_address_physical(clear_address),
2471 .use_clear_address = !anv_address_is_null(clear_address),
2472 .mocs = anv_mocs(device, state_inout->address.bo,
2473 view_usage),
2474 .x_offset_sa = tile_x_sa,
2475 .y_offset_sa = tile_y_sa);
2476
2477 /* With the exception of gfx8, the bottom 12 bits of the MCS base address
2478 * are used to store other information. This should be ok, however,
2479 * because the surface buffer addresses are always 4K page aligned.
2480 */
2481 if (!anv_address_is_null(aux_address)) {
2482 uint32_t *aux_addr_dw = state_inout->state.map +
2483 device->isl_dev.ss.aux_addr_offset;
2484 assert((aux_address.offset & 0xfff) == 0);
2485 state_inout->aux_address.offset |= *aux_addr_dw & 0xfff;
2486 }
2487
2488 if (device->info.ver >= 10 && clear_address.bo) {
2489 uint32_t *clear_addr_dw = state_inout->state.map +
2490 device->isl_dev.ss.clear_color_state_offset;
2491 assert((clear_address.offset & 0x3f) == 0);
2492 state_inout->clear_address.offset |= *clear_addr_dw & 0x3f;
2493 }
2494 }
2495
2496 if (image_param_out) {
2497 assert(view_usage == ISL_SURF_USAGE_STORAGE_BIT);
2498 isl_surf_fill_image_param(&device->isl_dev, image_param_out,
2499 &surface->isl, &view);
2500 }
2501 }
2502
2503 static uint32_t
anv_image_aspect_get_planes(VkImageAspectFlags aspect_mask)2504 anv_image_aspect_get_planes(VkImageAspectFlags aspect_mask)
2505 {
2506 anv_assert_valid_aspect_set(aspect_mask);
2507 return util_bitcount(aspect_mask);
2508 }
2509
2510 VkResult
anv_CreateImageView(VkDevice _device,const VkImageViewCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkImageView * pView)2511 anv_CreateImageView(VkDevice _device,
2512 const VkImageViewCreateInfo *pCreateInfo,
2513 const VkAllocationCallbacks *pAllocator,
2514 VkImageView *pView)
2515 {
2516 ANV_FROM_HANDLE(anv_device, device, _device);
2517 ANV_FROM_HANDLE(anv_image, image, pCreateInfo->image);
2518 struct anv_image_view *iview;
2519
2520 iview = vk_image_view_create(&device->vk, pCreateInfo,
2521 pAllocator, sizeof(*iview));
2522 if (iview == NULL)
2523 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
2524
2525 iview->image = image;
2526 iview->n_planes = anv_image_aspect_get_planes(iview->vk.aspects);
2527
2528 /* Check if a conversion info was passed. */
2529 const struct anv_format *conv_format = NULL;
2530 const VkSamplerYcbcrConversionInfo *conv_info =
2531 vk_find_struct_const(pCreateInfo->pNext, SAMPLER_YCBCR_CONVERSION_INFO);
2532
2533 #ifdef ANDROID
2534 /* If image has an external format, the pNext chain must contain an
2535 * instance of VKSamplerYcbcrConversionInfo with a conversion object
2536 * created with the same external format as image."
2537 */
2538 assert(!image->vk.android_external_format || conv_info);
2539 #endif
2540
2541 if (conv_info) {
2542 ANV_FROM_HANDLE(anv_ycbcr_conversion, conversion, conv_info->conversion);
2543 conv_format = conversion->format;
2544 }
2545
2546 #ifdef ANDROID
2547 /* "If image has an external format, format must be VK_FORMAT_UNDEFINED." */
2548 assert(!image->vk.android_external_format ||
2549 pCreateInfo->format == VK_FORMAT_UNDEFINED);
2550 #endif
2551
2552 /* Format is undefined, this can happen when using external formats. Set
2553 * view format from the passed conversion info.
2554 */
2555 if (iview->vk.format == VK_FORMAT_UNDEFINED && conv_format)
2556 iview->vk.format = conv_format->vk_format;
2557
2558 /* Now go through the underlying image selected planes and map them to
2559 * planes in the image view.
2560 */
2561 anv_foreach_image_aspect_bit(iaspect_bit, image, iview->vk.aspects) {
2562 const uint32_t iplane =
2563 anv_aspect_to_plane(image->vk.aspects, 1UL << iaspect_bit);
2564 const uint32_t vplane =
2565 anv_aspect_to_plane(iview->vk.aspects, 1UL << iaspect_bit);
2566 struct anv_format_plane format;
2567 format = anv_get_format_plane(&device->info, iview->vk.format,
2568 vplane, image->vk.tiling);
2569
2570 iview->planes[vplane].image_plane = iplane;
2571
2572 iview->planes[vplane].isl = (struct isl_view) {
2573 .format = format.isl_format,
2574 .base_level = iview->vk.base_mip_level,
2575 .levels = iview->vk.level_count,
2576 .base_array_layer = iview->vk.base_array_layer,
2577 .array_len = iview->vk.layer_count,
2578 .swizzle = {
2579 .r = remap_swizzle(iview->vk.swizzle.r, format.swizzle),
2580 .g = remap_swizzle(iview->vk.swizzle.g, format.swizzle),
2581 .b = remap_swizzle(iview->vk.swizzle.b, format.swizzle),
2582 .a = remap_swizzle(iview->vk.swizzle.a, format.swizzle),
2583 },
2584 };
2585
2586 if (pCreateInfo->viewType == VK_IMAGE_VIEW_TYPE_3D) {
2587 iview->planes[vplane].isl.base_array_layer = 0;
2588 iview->planes[vplane].isl.array_len = iview->vk.extent.depth;
2589 }
2590
2591 if (pCreateInfo->viewType == VK_IMAGE_VIEW_TYPE_CUBE ||
2592 pCreateInfo->viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) {
2593 iview->planes[vplane].isl.usage = ISL_SURF_USAGE_CUBE_BIT;
2594 } else {
2595 iview->planes[vplane].isl.usage = 0;
2596 }
2597
2598 if (iview->vk.usage & VK_IMAGE_USAGE_SAMPLED_BIT ||
2599 (iview->vk.usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT &&
2600 !(iview->vk.aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT_ANV))) {
2601 iview->planes[vplane].optimal_sampler_surface_state.state = alloc_surface_state(device);
2602 iview->planes[vplane].general_sampler_surface_state.state = alloc_surface_state(device);
2603
2604 enum isl_aux_usage general_aux_usage =
2605 anv_layout_to_aux_usage(&device->info, image, 1UL << iaspect_bit,
2606 VK_IMAGE_USAGE_SAMPLED_BIT,
2607 VK_IMAGE_LAYOUT_GENERAL);
2608 enum isl_aux_usage optimal_aux_usage =
2609 anv_layout_to_aux_usage(&device->info, image, 1UL << iaspect_bit,
2610 VK_IMAGE_USAGE_SAMPLED_BIT,
2611 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
2612
2613 anv_image_fill_surface_state(device, image, 1ULL << iaspect_bit,
2614 &iview->planes[vplane].isl,
2615 ISL_SURF_USAGE_TEXTURE_BIT,
2616 optimal_aux_usage, NULL,
2617 ANV_IMAGE_VIEW_STATE_TEXTURE_OPTIMAL,
2618 &iview->planes[vplane].optimal_sampler_surface_state,
2619 NULL);
2620
2621 anv_image_fill_surface_state(device, image, 1ULL << iaspect_bit,
2622 &iview->planes[vplane].isl,
2623 ISL_SURF_USAGE_TEXTURE_BIT,
2624 general_aux_usage, NULL,
2625 0,
2626 &iview->planes[vplane].general_sampler_surface_state,
2627 NULL);
2628 }
2629
2630 /* NOTE: This one needs to go last since it may stomp isl_view.format */
2631 if (iview->vk.usage & VK_IMAGE_USAGE_STORAGE_BIT) {
2632 iview->planes[vplane].storage_surface_state.state = alloc_surface_state(device);
2633 anv_image_fill_surface_state(device, image, 1ULL << iaspect_bit,
2634 &iview->planes[vplane].isl,
2635 ISL_SURF_USAGE_STORAGE_BIT,
2636 ISL_AUX_USAGE_NONE, NULL,
2637 0,
2638 &iview->planes[vplane].storage_surface_state,
2639 NULL);
2640
2641 if (isl_is_storage_image_format(format.isl_format)) {
2642 iview->planes[vplane].lowered_storage_surface_state.state =
2643 alloc_surface_state(device);
2644
2645 anv_image_fill_surface_state(device, image, 1ULL << iaspect_bit,
2646 &iview->planes[vplane].isl,
2647 ISL_SURF_USAGE_STORAGE_BIT,
2648 ISL_AUX_USAGE_NONE, NULL,
2649 ANV_IMAGE_VIEW_STATE_STORAGE_LOWERED,
2650 &iview->planes[vplane].lowered_storage_surface_state,
2651 &iview->planes[vplane].lowered_storage_image_param);
2652 } else {
2653 /* In this case, we support the format but, because there's no
2654 * SPIR-V format specifier corresponding to it, we only support it
2655 * if the hardware can do it natively. This is possible for some
2656 * reads but for most writes. Instead of hanging if someone gets
2657 * it wrong, we give them a NULL descriptor.
2658 */
2659 assert(isl_format_supports_typed_writes(&device->info,
2660 format.isl_format));
2661 iview->planes[vplane].lowered_storage_surface_state.state =
2662 device->null_surface_state;
2663 }
2664 }
2665 }
2666
2667 *pView = anv_image_view_to_handle(iview);
2668
2669 return VK_SUCCESS;
2670 }
2671
2672 void
anv_DestroyImageView(VkDevice _device,VkImageView _iview,const VkAllocationCallbacks * pAllocator)2673 anv_DestroyImageView(VkDevice _device, VkImageView _iview,
2674 const VkAllocationCallbacks *pAllocator)
2675 {
2676 ANV_FROM_HANDLE(anv_device, device, _device);
2677 ANV_FROM_HANDLE(anv_image_view, iview, _iview);
2678
2679 if (!iview)
2680 return;
2681
2682 for (uint32_t plane = 0; plane < iview->n_planes; plane++) {
2683 /* Check offset instead of alloc_size because this they might be
2684 * device->null_surface_state which always has offset == 0. We don't
2685 * own that one so we don't want to accidentally free it.
2686 */
2687 if (iview->planes[plane].optimal_sampler_surface_state.state.offset) {
2688 anv_state_pool_free(&device->surface_state_pool,
2689 iview->planes[plane].optimal_sampler_surface_state.state);
2690 }
2691
2692 if (iview->planes[plane].general_sampler_surface_state.state.offset) {
2693 anv_state_pool_free(&device->surface_state_pool,
2694 iview->planes[plane].general_sampler_surface_state.state);
2695 }
2696
2697 if (iview->planes[plane].storage_surface_state.state.offset) {
2698 anv_state_pool_free(&device->surface_state_pool,
2699 iview->planes[plane].storage_surface_state.state);
2700 }
2701
2702 if (iview->planes[plane].lowered_storage_surface_state.state.offset) {
2703 anv_state_pool_free(&device->surface_state_pool,
2704 iview->planes[plane].lowered_storage_surface_state.state);
2705 }
2706 }
2707
2708 vk_image_view_destroy(&device->vk, pAllocator, &iview->vk);
2709 }
2710
2711
2712 VkResult
anv_CreateBufferView(VkDevice _device,const VkBufferViewCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkBufferView * pView)2713 anv_CreateBufferView(VkDevice _device,
2714 const VkBufferViewCreateInfo *pCreateInfo,
2715 const VkAllocationCallbacks *pAllocator,
2716 VkBufferView *pView)
2717 {
2718 ANV_FROM_HANDLE(anv_device, device, _device);
2719 ANV_FROM_HANDLE(anv_buffer, buffer, pCreateInfo->buffer);
2720 struct anv_buffer_view *view;
2721
2722 view = vk_object_alloc(&device->vk, pAllocator, sizeof(*view),
2723 VK_OBJECT_TYPE_BUFFER_VIEW);
2724 if (!view)
2725 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
2726
2727 /* TODO: Handle the format swizzle? */
2728
2729 view->format = anv_get_isl_format(&device->info, pCreateInfo->format,
2730 VK_IMAGE_ASPECT_COLOR_BIT,
2731 VK_IMAGE_TILING_LINEAR);
2732 const uint32_t format_bs = isl_format_get_layout(view->format)->bpb / 8;
2733 view->range = anv_buffer_get_range(buffer, pCreateInfo->offset,
2734 pCreateInfo->range);
2735 view->range = align_down_npot_u32(view->range, format_bs);
2736
2737 view->address = anv_address_add(buffer->address, pCreateInfo->offset);
2738
2739 if (buffer->usage & VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT) {
2740 view->surface_state = alloc_surface_state(device);
2741
2742 anv_fill_buffer_surface_state(device, view->surface_state,
2743 view->format, ISL_SURF_USAGE_TEXTURE_BIT,
2744 view->address, view->range, format_bs);
2745 } else {
2746 view->surface_state = (struct anv_state){ 0 };
2747 }
2748
2749 if (buffer->usage & VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT) {
2750 view->storage_surface_state = alloc_surface_state(device);
2751 view->lowered_storage_surface_state = alloc_surface_state(device);
2752
2753 anv_fill_buffer_surface_state(device, view->storage_surface_state,
2754 view->format, ISL_SURF_USAGE_STORAGE_BIT,
2755 view->address, view->range,
2756 isl_format_get_layout(view->format)->bpb / 8);
2757
2758 enum isl_format lowered_format =
2759 isl_has_matching_typed_storage_image_format(&device->info,
2760 view->format) ?
2761 isl_lower_storage_image_format(&device->info, view->format) :
2762 ISL_FORMAT_RAW;
2763
2764 anv_fill_buffer_surface_state(device, view->lowered_storage_surface_state,
2765 lowered_format, ISL_SURF_USAGE_STORAGE_BIT,
2766 view->address, view->range,
2767 (lowered_format == ISL_FORMAT_RAW ? 1 :
2768 isl_format_get_layout(lowered_format)->bpb / 8));
2769
2770 isl_buffer_fill_image_param(&device->isl_dev,
2771 &view->lowered_storage_image_param,
2772 view->format, view->range);
2773 } else {
2774 view->storage_surface_state = (struct anv_state){ 0 };
2775 view->lowered_storage_surface_state = (struct anv_state){ 0 };
2776 }
2777
2778 *pView = anv_buffer_view_to_handle(view);
2779
2780 return VK_SUCCESS;
2781 }
2782
2783 void
anv_DestroyBufferView(VkDevice _device,VkBufferView bufferView,const VkAllocationCallbacks * pAllocator)2784 anv_DestroyBufferView(VkDevice _device, VkBufferView bufferView,
2785 const VkAllocationCallbacks *pAllocator)
2786 {
2787 ANV_FROM_HANDLE(anv_device, device, _device);
2788 ANV_FROM_HANDLE(anv_buffer_view, view, bufferView);
2789
2790 if (!view)
2791 return;
2792
2793 if (view->surface_state.alloc_size > 0)
2794 anv_state_pool_free(&device->surface_state_pool,
2795 view->surface_state);
2796
2797 if (view->storage_surface_state.alloc_size > 0)
2798 anv_state_pool_free(&device->surface_state_pool,
2799 view->storage_surface_state);
2800
2801 if (view->lowered_storage_surface_state.alloc_size > 0)
2802 anv_state_pool_free(&device->surface_state_pool,
2803 view->lowered_storage_surface_state);
2804
2805 vk_object_free(&device->vk, pAllocator, view);
2806 }
2807