anv: modify the internal concept of format to express multiple planes
[mesa.git] / src / intel / vulkan / anv_image.c
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
31 #include "anv_private.h"
32 #include "util/debug.h"
33 #include "vk_util.h"
34
35 #include "vk_format_info.h"
36
37 /**
38 * Exactly one bit must be set in \a aspect.
39 */
40 static isl_surf_usage_flags_t
41 choose_isl_surf_usage(VkImageCreateFlags vk_create_flags,
42 VkImageUsageFlags vk_usage,
43 VkImageAspectFlags aspect)
44 {
45 isl_surf_usage_flags_t isl_usage = 0;
46
47 if (vk_usage & VK_IMAGE_USAGE_SAMPLED_BIT)
48 isl_usage |= ISL_SURF_USAGE_TEXTURE_BIT;
49
50 if (vk_usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)
51 isl_usage |= ISL_SURF_USAGE_TEXTURE_BIT;
52
53 if (vk_usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
54 isl_usage |= ISL_SURF_USAGE_RENDER_TARGET_BIT;
55
56 if (vk_create_flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT)
57 isl_usage |= ISL_SURF_USAGE_CUBE_BIT;
58
59 /* Even if we're only using it for transfer operations, clears to depth and
60 * stencil images happen as depth and stencil so they need the right ISL
61 * usage bits or else things will fall apart.
62 */
63 switch (aspect) {
64 case VK_IMAGE_ASPECT_DEPTH_BIT:
65 isl_usage |= ISL_SURF_USAGE_DEPTH_BIT;
66 break;
67 case VK_IMAGE_ASPECT_STENCIL_BIT:
68 isl_usage |= ISL_SURF_USAGE_STENCIL_BIT;
69 break;
70 case VK_IMAGE_ASPECT_COLOR_BIT:
71 break;
72 default:
73 unreachable("bad VkImageAspect");
74 }
75
76 if (vk_usage & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) {
77 /* blorp implements transfers by sampling from the source image. */
78 isl_usage |= ISL_SURF_USAGE_TEXTURE_BIT;
79 }
80
81 if (vk_usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT &&
82 aspect == VK_IMAGE_ASPECT_COLOR_BIT) {
83 /* blorp implements transfers by rendering into the destination image.
84 * Only request this with color images, as we deal with depth/stencil
85 * formats differently. */
86 isl_usage |= ISL_SURF_USAGE_RENDER_TARGET_BIT;
87 }
88
89 return isl_usage;
90 }
91
92 /**
93 * Exactly one bit must be set in \a aspect.
94 */
95 static struct anv_surface *
96 get_surface(struct anv_image *image, VkImageAspectFlags aspect)
97 {
98 switch (aspect) {
99 default:
100 unreachable("bad VkImageAspect");
101 case VK_IMAGE_ASPECT_COLOR_BIT:
102 return &image->color_surface;
103 case VK_IMAGE_ASPECT_DEPTH_BIT:
104 return &image->depth_surface;
105 case VK_IMAGE_ASPECT_STENCIL_BIT:
106 return &image->stencil_surface;
107 }
108 }
109
110 static void
111 add_surface(struct anv_image *image, struct anv_surface *surf)
112 {
113 assert(surf->isl.size > 0); /* isl surface must be initialized */
114
115 surf->offset = align_u32(image->size, surf->isl.alignment);
116 image->size = surf->offset + surf->isl.size;
117 image->alignment = MAX2(image->alignment, surf->isl.alignment);
118 }
119
120
121 static bool
122 all_formats_ccs_e_compatible(const struct gen_device_info *devinfo,
123 const struct VkImageCreateInfo *vk_info)
124 {
125 enum isl_format format =
126 anv_get_isl_format(devinfo, vk_info->format,
127 VK_IMAGE_ASPECT_COLOR_BIT, vk_info->tiling);
128
129 if (!isl_format_supports_ccs_e(devinfo, format))
130 return false;
131
132 if (!(vk_info->flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT))
133 return true;
134
135 const VkImageFormatListCreateInfoKHR *fmt_list =
136 vk_find_struct_const(vk_info->pNext, IMAGE_FORMAT_LIST_CREATE_INFO_KHR);
137
138 if (!fmt_list || fmt_list->viewFormatCount == 0)
139 return false;
140
141 for (uint32_t i = 0; i < fmt_list->viewFormatCount; i++) {
142 enum isl_format view_format =
143 anv_get_isl_format(devinfo, fmt_list->pViewFormats[i],
144 VK_IMAGE_ASPECT_COLOR_BIT, vk_info->tiling);
145
146 if (!isl_formats_are_ccs_e_compatible(devinfo, format, view_format))
147 return false;
148 }
149
150 return true;
151 }
152
153 /**
154 * For color images that have an auxiliary surface, request allocation for an
155 * additional buffer that mainly stores fast-clear values. Use of this buffer
156 * allows us to access the image's subresources while being aware of their
157 * fast-clear values in non-trivial cases (e.g., outside of a render pass in
158 * which a fast clear has occurred).
159 *
160 * For the purpose of discoverability, the algorithm used to manage this buffer
161 * is described here. A clear value in this buffer is updated when a fast clear
162 * is performed on a subresource. One of two synchronization operations is
163 * performed in order for a following memory access to use the fast-clear
164 * value:
165 * a. Copy the value from the buffer to the surface state object used for
166 * reading. This is done implicitly when the value is the clear value
167 * predetermined to be the default in other surface state objects. This
168 * is currently only done explicitly for the operation below.
169 * b. Do (a) and use the surface state object to resolve the subresource.
170 * This is only done during layout transitions for decent performance.
171 *
172 * With the above scheme, we can fast-clear whenever the hardware allows except
173 * for two cases in which synchronization becomes impossible or undesirable:
174 * * The subresource is in the GENERAL layout and is cleared to a value
175 * other than the special default value.
176 *
177 * Performing a synchronization operation in order to read from the
178 * subresource is undesirable in this case. Firstly, b) is not an option
179 * because a layout transition isn't required between a write and read of
180 * an image in the GENERAL layout. Secondly, it's undesirable to do a)
181 * explicitly because it would require large infrastructural changes. The
182 * Vulkan API supports us in deciding not to optimize this layout by
183 * stating that using this layout may cause suboptimal performance. NOTE:
184 * the auxiliary buffer must always be enabled to support a) implicitly.
185 *
186 *
187 * * For the given miplevel, only some of the layers are cleared at once.
188 *
189 * If the user clears each layer to a different value, then tries to
190 * render to multiple layers at once, we have no ability to perform a
191 * synchronization operation in between. a) is not helpful because the
192 * object can only hold one clear value. b) is not an option because a
193 * layout transition isn't required in this case.
194 */
195 static void
196 add_fast_clear_state_buffer(struct anv_image *image,
197 const struct anv_device *device)
198 {
199 assert(image && device);
200 assert(image->aux_surface.isl.size > 0 &&
201 image->aspects == VK_IMAGE_ASPECT_COLOR_BIT);
202
203 /* The offset to the buffer of clear values must be dword-aligned for GPU
204 * memcpy operations. It is located immediately after the auxiliary surface.
205 */
206
207 /* Tiled images are guaranteed to be 4K aligned, so the image alignment
208 * should also be dword-aligned.
209 */
210 assert(image->alignment % 4 == 0);
211
212 /* Auxiliary buffers should be a multiple of 4K, so the start of the clear
213 * values buffer should already be dword-aligned.
214 */
215 assert(image->aux_surface.isl.size % 4 == 0);
216
217 /* This buffer should be at the very end of the image. */
218 assert(image->size ==
219 image->aux_surface.offset + image->aux_surface.isl.size);
220
221 const unsigned entry_size = anv_fast_clear_state_entry_size(device);
222 /* There's no padding between entries, so ensure that they're always a
223 * multiple of 32 bits in order to enable GPU memcpy operations.
224 */
225 assert(entry_size % 4 == 0);
226 image->size += entry_size * anv_image_aux_levels(image);
227 }
228
229 /**
230 * Initialize the anv_image::*_surface selected by \a aspect. Then update the
231 * image's memory requirements (that is, the image's size and alignment).
232 *
233 * Exactly one bit must be set in \a aspect.
234 */
235 static VkResult
236 make_surface(const struct anv_device *dev,
237 struct anv_image *image,
238 const struct anv_image_create_info *anv_info,
239 VkImageAspectFlags aspect)
240 {
241 const VkImageCreateInfo *vk_info = anv_info->vk_info;
242 bool ok UNUSED;
243
244 static const enum isl_surf_dim vk_to_isl_surf_dim[] = {
245 [VK_IMAGE_TYPE_1D] = ISL_SURF_DIM_1D,
246 [VK_IMAGE_TYPE_2D] = ISL_SURF_DIM_2D,
247 [VK_IMAGE_TYPE_3D] = ISL_SURF_DIM_3D,
248 };
249
250 /* Translate the Vulkan tiling to an equivalent ISL tiling, then filter the
251 * result with an optionally provided ISL tiling argument.
252 */
253 isl_tiling_flags_t tiling_flags =
254 (vk_info->tiling == VK_IMAGE_TILING_LINEAR) ?
255 ISL_TILING_LINEAR_BIT : ISL_TILING_ANY_MASK;
256
257 if (anv_info->isl_tiling_flags)
258 tiling_flags &= anv_info->isl_tiling_flags;
259
260 assert(tiling_flags);
261
262 struct anv_surface *anv_surf = get_surface(image, aspect);
263
264 image->extent = anv_sanitize_image_extent(vk_info->imageType,
265 vk_info->extent);
266
267 enum isl_format format = anv_get_isl_format(&dev->info, vk_info->format,
268 aspect, vk_info->tiling);
269 assert(format != ISL_FORMAT_UNSUPPORTED);
270
271 /* If an image is created as BLOCK_TEXEL_VIEW_COMPATIBLE, then we need to
272 * fall back to linear on Broadwell and earlier because we aren't
273 * guaranteed that we can handle offsets correctly. On Sky Lake, the
274 * horizontal and vertical alignments are sufficiently high that we can
275 * just use RENDER_SURFACE_STATE::X/Y Offset.
276 */
277 bool needs_shadow = false;
278 if (dev->info.gen <= 8 &&
279 (vk_info->flags & VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT_KHR) &&
280 vk_info->tiling == VK_IMAGE_TILING_OPTIMAL) {
281 assert(isl_format_is_compressed(format));
282 tiling_flags = ISL_TILING_LINEAR_BIT;
283 needs_shadow = true;
284 }
285
286 ok = isl_surf_init(&dev->isl_dev, &anv_surf->isl,
287 .dim = vk_to_isl_surf_dim[vk_info->imageType],
288 .format = format,
289 .width = image->extent.width,
290 .height = image->extent.height,
291 .depth = image->extent.depth,
292 .levels = vk_info->mipLevels,
293 .array_len = vk_info->arrayLayers,
294 .samples = vk_info->samples,
295 .min_alignment = 0,
296 .row_pitch = anv_info->stride,
297 .usage = choose_isl_surf_usage(vk_info->flags, image->usage, aspect),
298 .tiling_flags = tiling_flags);
299
300 /* isl_surf_init() will fail only if provided invalid input. Invalid input
301 * is illegal in Vulkan.
302 */
303 assert(ok);
304
305 add_surface(image, anv_surf);
306
307 /* If an image is created as BLOCK_TEXEL_VIEW_COMPATIBLE, then we need to
308 * create an identical tiled shadow surface for use while texturing so we
309 * don't get garbage performance.
310 */
311 if (needs_shadow) {
312 assert(aspect == VK_IMAGE_ASPECT_COLOR_BIT);
313 assert(tiling_flags == ISL_TILING_LINEAR_BIT);
314
315 ok = isl_surf_init(&dev->isl_dev, &image->shadow_surface.isl,
316 .dim = vk_to_isl_surf_dim[vk_info->imageType],
317 .format = format,
318 .width = image->extent.width,
319 .height = image->extent.height,
320 .depth = image->extent.depth,
321 .levels = vk_info->mipLevels,
322 .array_len = vk_info->arrayLayers,
323 .samples = vk_info->samples,
324 .min_alignment = 0,
325 .row_pitch = anv_info->stride,
326 .usage = choose_isl_surf_usage(image->usage, image->usage, aspect),
327 .tiling_flags = ISL_TILING_ANY_MASK);
328
329 /* isl_surf_init() will fail only if provided invalid input. Invalid input
330 * is illegal in Vulkan.
331 */
332 assert(ok);
333
334 add_surface(image, &image->shadow_surface);
335 }
336
337 /* Add a HiZ surface to a depth buffer that will be used for rendering.
338 */
339 if (aspect == VK_IMAGE_ASPECT_DEPTH_BIT) {
340 /* We don't advertise that depth buffers could be used as storage
341 * images.
342 */
343 assert(!(image->usage & VK_IMAGE_USAGE_STORAGE_BIT));
344
345 /* Allow the user to control HiZ enabling. Disable by default on gen7
346 * because resolves are not currently implemented pre-BDW.
347 */
348 if (!(image->usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) {
349 /* It will never be used as an attachment, HiZ is pointless. */
350 } else if (dev->info.gen == 7) {
351 anv_perf_warn(dev->instance, image, "Implement gen7 HiZ");
352 } else if (vk_info->mipLevels > 1) {
353 anv_perf_warn(dev->instance, image, "Enable multi-LOD HiZ");
354 } else if (vk_info->arrayLayers > 1) {
355 anv_perf_warn(dev->instance, image,
356 "Implement multi-arrayLayer HiZ clears and resolves");
357 } else if (dev->info.gen == 8 && vk_info->samples > 1) {
358 anv_perf_warn(dev->instance, image, "Enable gen8 multisampled HiZ");
359 } else if (!unlikely(INTEL_DEBUG & DEBUG_NO_HIZ)) {
360 assert(image->aux_surface.isl.size == 0);
361 ok = isl_surf_get_hiz_surf(&dev->isl_dev, &image->depth_surface.isl,
362 &image->aux_surface.isl);
363 assert(ok);
364 add_surface(image, &image->aux_surface);
365 image->aux_usage = ISL_AUX_USAGE_HIZ;
366 }
367 } else if (aspect == VK_IMAGE_ASPECT_COLOR_BIT && vk_info->samples == 1) {
368 if (!unlikely(INTEL_DEBUG & DEBUG_NO_RBC)) {
369 assert(image->aux_surface.isl.size == 0);
370 ok = isl_surf_get_ccs_surf(&dev->isl_dev, &anv_surf->isl,
371 &image->aux_surface.isl, 0);
372 if (ok) {
373
374 /* Disable CCS when it is not useful (i.e., when you can't render
375 * to the image with CCS enabled).
376 */
377 if (!isl_format_supports_rendering(&dev->info, format)) {
378 /* While it may be technically possible to enable CCS for this
379 * image, we currently don't have things hooked up to get it
380 * working.
381 */
382 anv_perf_warn(dev->instance, image,
383 "This image format doesn't support rendering. "
384 "Not allocating an CCS buffer.");
385 image->aux_surface.isl.size = 0;
386 return VK_SUCCESS;
387 }
388
389 add_surface(image, &image->aux_surface);
390 add_fast_clear_state_buffer(image, dev);
391
392 /* For images created without MUTABLE_FORMAT_BIT set, we know that
393 * they will always be used with the original format. In
394 * particular, they will always be used with a format that
395 * supports color compression. If it's never used as a storage
396 * image, then it will only be used through the sampler or the as
397 * a render target. This means that it's safe to just leave
398 * compression on at all times for these formats.
399 */
400 if (!(vk_info->usage & VK_IMAGE_USAGE_STORAGE_BIT) &&
401 all_formats_ccs_e_compatible(&dev->info, vk_info)) {
402 image->aux_usage = ISL_AUX_USAGE_CCS_E;
403 }
404 }
405 }
406 } else if (aspect == VK_IMAGE_ASPECT_COLOR_BIT && vk_info->samples > 1) {
407 assert(image->aux_surface.isl.size == 0);
408 assert(!(vk_info->usage & VK_IMAGE_USAGE_STORAGE_BIT));
409 ok = isl_surf_get_mcs_surf(&dev->isl_dev, &anv_surf->isl,
410 &image->aux_surface.isl);
411 if (ok) {
412 add_surface(image, &image->aux_surface);
413 add_fast_clear_state_buffer(image, dev);
414 image->aux_usage = ISL_AUX_USAGE_MCS;
415 }
416 }
417
418 return VK_SUCCESS;
419 }
420
421 VkResult
422 anv_image_create(VkDevice _device,
423 const struct anv_image_create_info *create_info,
424 const VkAllocationCallbacks* alloc,
425 VkImage *pImage)
426 {
427 ANV_FROM_HANDLE(anv_device, device, _device);
428 const VkImageCreateInfo *pCreateInfo = create_info->vk_info;
429 struct anv_image *image = NULL;
430 VkResult r;
431
432 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO);
433
434 anv_assert(pCreateInfo->mipLevels > 0);
435 anv_assert(pCreateInfo->arrayLayers > 0);
436 anv_assert(pCreateInfo->samples > 0);
437 anv_assert(pCreateInfo->extent.width > 0);
438 anv_assert(pCreateInfo->extent.height > 0);
439 anv_assert(pCreateInfo->extent.depth > 0);
440
441 image = vk_zalloc2(&device->alloc, alloc, sizeof(*image), 8,
442 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
443 if (!image)
444 return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
445
446 image->type = pCreateInfo->imageType;
447 image->extent = pCreateInfo->extent;
448 image->vk_format = pCreateInfo->format;
449 image->aspects = vk_format_aspects(image->vk_format);
450 image->levels = pCreateInfo->mipLevels;
451 image->array_size = pCreateInfo->arrayLayers;
452 image->samples = pCreateInfo->samples;
453 image->usage = pCreateInfo->usage;
454 image->tiling = pCreateInfo->tiling;
455 image->aux_usage = ISL_AUX_USAGE_NONE;
456
457 uint32_t b;
458 for_each_bit(b, image->aspects) {
459 r = make_surface(device, image, create_info, (1 << b));
460 if (r != VK_SUCCESS)
461 goto fail;
462 }
463
464 *pImage = anv_image_to_handle(image);
465
466 return VK_SUCCESS;
467
468 fail:
469 if (image)
470 vk_free2(&device->alloc, alloc, image);
471
472 return r;
473 }
474
475 VkResult
476 anv_CreateImage(VkDevice device,
477 const VkImageCreateInfo *pCreateInfo,
478 const VkAllocationCallbacks *pAllocator,
479 VkImage *pImage)
480 {
481 return anv_image_create(device,
482 &(struct anv_image_create_info) {
483 .vk_info = pCreateInfo,
484 },
485 pAllocator,
486 pImage);
487 }
488
489 void
490 anv_DestroyImage(VkDevice _device, VkImage _image,
491 const VkAllocationCallbacks *pAllocator)
492 {
493 ANV_FROM_HANDLE(anv_device, device, _device);
494 ANV_FROM_HANDLE(anv_image, image, _image);
495
496 if (!image)
497 return;
498
499 vk_free2(&device->alloc, pAllocator, image);
500 }
501
502 static void
503 anv_bind_image_memory(const VkBindImageMemoryInfoKHR *pBindInfo)
504 {
505 ANV_FROM_HANDLE(anv_device_memory, mem, pBindInfo->memory);
506 ANV_FROM_HANDLE(anv_image, image, pBindInfo->image);
507
508 assert(pBindInfo->sType == VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO_KHR);
509
510 if (mem == NULL) {
511 image->bo = NULL;
512 image->offset = 0;
513 return;
514 }
515
516 image->bo = mem->bo;
517 image->offset = pBindInfo->memoryOffset;
518 }
519
520 VkResult anv_BindImageMemory(
521 VkDevice device,
522 VkImage image,
523 VkDeviceMemory memory,
524 VkDeviceSize memoryOffset)
525 {
526 anv_bind_image_memory(
527 &(VkBindImageMemoryInfoKHR) {
528 .sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO_KHR,
529 .image = image,
530 .memory = memory,
531 .memoryOffset = memoryOffset,
532 });
533
534 return VK_SUCCESS;
535 }
536
537 VkResult anv_BindImageMemory2KHR(
538 VkDevice device,
539 uint32_t bindInfoCount,
540 const VkBindImageMemoryInfoKHR* pBindInfos)
541 {
542 for (uint32_t i = 0; i < bindInfoCount; i++)
543 anv_bind_image_memory(&pBindInfos[i]);
544
545 return VK_SUCCESS;
546 }
547
548 static void
549 anv_surface_get_subresource_layout(struct anv_image *image,
550 struct anv_surface *surface,
551 const VkImageSubresource *subresource,
552 VkSubresourceLayout *layout)
553 {
554 /* If we are on a non-zero mip level or array slice, we need to
555 * calculate a real offset.
556 */
557 anv_assert(subresource->mipLevel == 0);
558 anv_assert(subresource->arrayLayer == 0);
559
560 layout->offset = surface->offset;
561 layout->rowPitch = surface->isl.row_pitch;
562 layout->depthPitch = isl_surf_get_array_pitch(&surface->isl);
563 layout->arrayPitch = isl_surf_get_array_pitch(&surface->isl);
564 layout->size = surface->isl.size;
565 }
566
567 void anv_GetImageSubresourceLayout(
568 VkDevice device,
569 VkImage _image,
570 const VkImageSubresource* pSubresource,
571 VkSubresourceLayout* pLayout)
572 {
573 ANV_FROM_HANDLE(anv_image, image, _image);
574
575 assert(__builtin_popcount(pSubresource->aspectMask) == 1);
576
577 switch (pSubresource->aspectMask) {
578 case VK_IMAGE_ASPECT_COLOR_BIT:
579 anv_surface_get_subresource_layout(image, &image->color_surface,
580 pSubresource, pLayout);
581 break;
582 case VK_IMAGE_ASPECT_DEPTH_BIT:
583 anv_surface_get_subresource_layout(image, &image->depth_surface,
584 pSubresource, pLayout);
585 break;
586 case VK_IMAGE_ASPECT_STENCIL_BIT:
587 anv_surface_get_subresource_layout(image, &image->stencil_surface,
588 pSubresource, pLayout);
589 break;
590 default:
591 assert(!"Invalid image aspect");
592 }
593 }
594
595 /**
596 * This function determines the optimal buffer to use for a given
597 * VkImageLayout and other pieces of information needed to make that
598 * determination. This does not determine the optimal buffer to use
599 * during a resolve operation.
600 *
601 * @param devinfo The device information of the Intel GPU.
602 * @param image The image that may contain a collection of buffers.
603 * @param aspects The aspect(s) of the image to be accessed.
604 * @param layout The current layout of the image aspect(s).
605 *
606 * @return The primary buffer that should be used for the given layout.
607 */
608 enum isl_aux_usage
609 anv_layout_to_aux_usage(const struct gen_device_info * const devinfo,
610 const struct anv_image * const image,
611 const VkImageAspectFlags aspects,
612 const VkImageLayout layout)
613 {
614 /* Validate the inputs. */
615
616 /* The devinfo is needed as the optimal buffer varies across generations. */
617 assert(devinfo != NULL);
618
619 /* The layout of a NULL image is not properly defined. */
620 assert(image != NULL);
621
622 /* The aspects must be a subset of the image aspects. */
623 assert(aspects & image->aspects && aspects <= image->aspects);
624
625 /* Determine the optimal buffer. */
626
627 /* If there is no auxiliary surface allocated, we must use the one and only
628 * main buffer.
629 */
630 if (image->aux_surface.isl.size == 0)
631 return ISL_AUX_USAGE_NONE;
632
633 /* All images that use an auxiliary surface are required to be tiled. */
634 assert(image->tiling == VK_IMAGE_TILING_OPTIMAL);
635
636 /* On BDW+, when clearing the stencil aspect of a depth stencil image,
637 * the HiZ buffer allows us to record the clear with a relatively small
638 * number of packets. Prior to BDW, the HiZ buffer provides no known benefit
639 * to the stencil aspect.
640 */
641 if (devinfo->gen < 8 && aspects == VK_IMAGE_ASPECT_STENCIL_BIT)
642 return ISL_AUX_USAGE_NONE;
643
644 const bool color_aspect = aspects == VK_IMAGE_ASPECT_COLOR_BIT;
645
646 /* The following switch currently only handles depth stencil aspects.
647 * TODO: Handle the color aspect.
648 */
649 if (color_aspect)
650 return image->aux_usage;
651
652 switch (layout) {
653
654 /* Invalid Layouts */
655 case VK_IMAGE_LAYOUT_RANGE_SIZE:
656 case VK_IMAGE_LAYOUT_MAX_ENUM:
657 unreachable("Invalid image layout.");
658
659 /* Undefined layouts
660 *
661 * The pre-initialized layout is equivalent to the undefined layout for
662 * optimally-tiled images. We can only do color compression (CCS or HiZ)
663 * on tiled images.
664 */
665 case VK_IMAGE_LAYOUT_UNDEFINED:
666 case VK_IMAGE_LAYOUT_PREINITIALIZED:
667 return ISL_AUX_USAGE_NONE;
668
669
670 /* Transfer Layouts
671 *
672 * This buffer could be a depth buffer used in a transfer operation. BLORP
673 * currently doesn't use HiZ for transfer operations so we must use the main
674 * buffer for this layout. TODO: Enable HiZ in BLORP.
675 */
676 case VK_IMAGE_LAYOUT_GENERAL:
677 case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
678 case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
679 return ISL_AUX_USAGE_NONE;
680
681
682 /* Sampling Layouts */
683 case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
684 assert(!color_aspect);
685 /* Fall-through */
686 case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
687 case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL_KHR:
688 if (anv_can_sample_with_hiz(devinfo, aspects, image->samples))
689 return ISL_AUX_USAGE_HIZ;
690 else
691 return ISL_AUX_USAGE_NONE;
692
693 case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:
694 assert(color_aspect);
695
696 /* On SKL+, the render buffer can be decompressed by the presentation
697 * engine. Support for this feature has not yet landed in the wider
698 * ecosystem. TODO: Update this code when support lands.
699 *
700 * From the BDW PRM, Vol 7, Render Target Resolve:
701 *
702 * If the MCS is enabled on a non-multisampled render target, the
703 * render target must be resolved before being used for other
704 * purposes (display, texture, CPU lock) The clear value from
705 * SURFACE_STATE is written into pixels in the render target
706 * indicated as clear in the MCS.
707 *
708 * Pre-SKL, the render buffer must be resolved before being used for
709 * presentation. We can infer that the auxiliary buffer is not used.
710 */
711 return ISL_AUX_USAGE_NONE;
712
713
714 /* Rendering Layouts */
715 case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
716 assert(color_aspect);
717 unreachable("Color images are not yet supported.");
718
719 case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
720 case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL_KHR:
721 assert(!color_aspect);
722 return ISL_AUX_USAGE_HIZ;
723
724 case VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR:
725 unreachable("VK_KHR_shared_presentable_image is unsupported");
726 }
727
728 /* If the layout isn't recognized in the exhaustive switch above, the
729 * VkImageLayout value is not defined in vulkan.h.
730 */
731 unreachable("layout is not a VkImageLayout enumeration member.");
732 }
733
734
735 static struct anv_state
736 alloc_surface_state(struct anv_device *device)
737 {
738 return anv_state_pool_alloc(&device->surface_state_pool, 64, 64);
739 }
740
741 static enum isl_channel_select
742 remap_swizzle(VkComponentSwizzle swizzle, VkComponentSwizzle component,
743 struct isl_swizzle format_swizzle)
744 {
745 if (swizzle == VK_COMPONENT_SWIZZLE_IDENTITY)
746 swizzle = component;
747
748 switch (swizzle) {
749 case VK_COMPONENT_SWIZZLE_ZERO: return ISL_CHANNEL_SELECT_ZERO;
750 case VK_COMPONENT_SWIZZLE_ONE: return ISL_CHANNEL_SELECT_ONE;
751 case VK_COMPONENT_SWIZZLE_R: return format_swizzle.r;
752 case VK_COMPONENT_SWIZZLE_G: return format_swizzle.g;
753 case VK_COMPONENT_SWIZZLE_B: return format_swizzle.b;
754 case VK_COMPONENT_SWIZZLE_A: return format_swizzle.a;
755 default:
756 unreachable("Invalid swizzle");
757 }
758 }
759
760 void
761 anv_image_fill_surface_state(struct anv_device *device,
762 const struct anv_image *image,
763 VkImageAspectFlagBits aspect,
764 const struct isl_view *view_in,
765 isl_surf_usage_flags_t view_usage,
766 enum isl_aux_usage aux_usage,
767 const union isl_color_value *clear_color,
768 enum anv_image_view_state_flags flags,
769 struct anv_surface_state *state_inout,
770 struct brw_image_param *image_param_out)
771 {
772 const struct anv_surface *surface =
773 anv_image_get_surface_for_aspect_mask(image, aspect);
774
775 struct isl_view view = *view_in;
776 view.usage |= view_usage;
777
778 /* For texturing with VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL from a
779 * compressed surface with a shadow surface, we use the shadow instead of
780 * the primary surface. The shadow surface will be tiled, unlike the main
781 * surface, so it should get significantly better performance.
782 */
783 if (image->shadow_surface.isl.size > 0 &&
784 isl_format_is_compressed(view.format) &&
785 (flags & ANV_IMAGE_VIEW_STATE_TEXTURE_OPTIMAL)) {
786 assert(isl_format_is_compressed(surface->isl.format));
787 assert(surface->isl.tiling == ISL_TILING_LINEAR);
788 assert(image->shadow_surface.isl.tiling != ISL_TILING_LINEAR);
789 surface = &image->shadow_surface;
790 }
791
792 if (view_usage == ISL_SURF_USAGE_RENDER_TARGET_BIT)
793 view.swizzle = anv_swizzle_for_render(view.swizzle);
794
795 /* If this is a HiZ buffer we can sample from with a programmable clear
796 * value (SKL+), define the clear value to the optimal constant.
797 */
798 union isl_color_value default_clear_color = { .u32 = { 0, } };
799 if (device->info.gen >= 9 && aux_usage == ISL_AUX_USAGE_HIZ)
800 default_clear_color.f32[0] = ANV_HZ_FC_VAL;
801 if (!clear_color)
802 clear_color = &default_clear_color;
803
804 const uint64_t address = image->offset + surface->offset;
805 const uint64_t aux_address = (aux_usage == ISL_AUX_USAGE_NONE) ? 0 :
806 image->offset + image->aux_surface.offset;
807
808 if (view_usage == ISL_SURF_USAGE_STORAGE_BIT &&
809 !(flags & ANV_IMAGE_VIEW_STATE_STORAGE_WRITE_ONLY) &&
810 !isl_has_matching_typed_storage_image_format(&device->info,
811 view.format)) {
812 /* In this case, we are a writeable storage buffer which needs to be
813 * lowered to linear. All tiling and offset calculations will be done in
814 * the shader.
815 */
816 assert(aux_usage == ISL_AUX_USAGE_NONE);
817 isl_buffer_fill_state(&device->isl_dev, state_inout->state.map,
818 .address = address,
819 .size = surface->isl.size,
820 .format = ISL_FORMAT_RAW,
821 .stride = 1,
822 .mocs = device->default_mocs);
823 state_inout->address = address,
824 state_inout->aux_address = 0;
825 } else {
826 if (view_usage == ISL_SURF_USAGE_STORAGE_BIT &&
827 !(flags & ANV_IMAGE_VIEW_STATE_STORAGE_WRITE_ONLY)) {
828 /* Typed surface reads support a very limited subset of the shader
829 * image formats. Translate it into the closest format the hardware
830 * supports.
831 */
832 assert(aux_usage == ISL_AUX_USAGE_NONE);
833 view.format = isl_lower_storage_image_format(&device->info,
834 view.format);
835 }
836
837 const struct isl_surf *isl_surf = &surface->isl;
838
839 struct isl_surf tmp_surf;
840 uint32_t offset_B = 0, tile_x_sa = 0, tile_y_sa = 0;
841 if (isl_format_is_compressed(surface->isl.format) &&
842 !isl_format_is_compressed(view.format)) {
843 /* We're creating an uncompressed view of a compressed surface. This
844 * is allowed but only for a single level/layer.
845 */
846 assert(surface->isl.samples == 1);
847 assert(view.levels == 1);
848 assert(view.array_len == 1);
849
850 isl_surf_get_image_surf(&device->isl_dev, isl_surf,
851 view.base_level,
852 surface->isl.dim == ISL_SURF_DIM_3D ?
853 0 : view.base_array_layer,
854 surface->isl.dim == ISL_SURF_DIM_3D ?
855 view.base_array_layer : 0,
856 &tmp_surf,
857 &offset_B, &tile_x_sa, &tile_y_sa);
858
859 /* The newly created image represents the one subimage we're
860 * referencing with this view so it only has one array slice and
861 * miplevel.
862 */
863 view.base_array_layer = 0;
864 view.base_level = 0;
865
866 /* We're making an uncompressed view here. The image dimensions need
867 * to be scaled down by the block size.
868 */
869 const struct isl_format_layout *fmtl =
870 isl_format_get_layout(surface->isl.format);
871 tmp_surf.format = view.format;
872 tmp_surf.logical_level0_px.width =
873 DIV_ROUND_UP(tmp_surf.logical_level0_px.width, fmtl->bw);
874 tmp_surf.logical_level0_px.height =
875 DIV_ROUND_UP(tmp_surf.logical_level0_px.height, fmtl->bh);
876 tmp_surf.phys_level0_sa.width /= fmtl->bw;
877 tmp_surf.phys_level0_sa.height /= fmtl->bh;
878 tile_x_sa /= fmtl->bw;
879 tile_y_sa /= fmtl->bh;
880
881 isl_surf = &tmp_surf;
882
883 if (device->info.gen <= 8) {
884 assert(surface->isl.tiling == ISL_TILING_LINEAR);
885 assert(tile_x_sa == 0);
886 assert(tile_y_sa == 0);
887 }
888 }
889
890 isl_surf_fill_state(&device->isl_dev, state_inout->state.map,
891 .surf = isl_surf,
892 .view = &view,
893 .address = address + offset_B,
894 .clear_color = *clear_color,
895 .aux_surf = &image->aux_surface.isl,
896 .aux_usage = aux_usage,
897 .aux_address = aux_address,
898 .mocs = device->default_mocs,
899 .x_offset_sa = tile_x_sa,
900 .y_offset_sa = tile_y_sa);
901 state_inout->address = address + offset_B;
902 if (device->info.gen >= 8) {
903 state_inout->aux_address = aux_address;
904 } else {
905 /* On gen7 and prior, the bottom 12 bits of the MCS base address are
906 * used to store other information. This should be ok, however,
907 * because surface buffer addresses are always 4K page alinged.
908 */
909 uint32_t *aux_addr_dw = state_inout->state.map +
910 device->isl_dev.ss.aux_addr_offset;
911 assert((aux_address & 0xfff) == 0);
912 assert(aux_address == (*aux_addr_dw & 0xfffff000));
913 state_inout->aux_address = *aux_addr_dw;
914 }
915 }
916
917 anv_state_flush(device, state_inout->state);
918
919 if (image_param_out) {
920 assert(view_usage == ISL_SURF_USAGE_STORAGE_BIT);
921 isl_surf_fill_image_param(&device->isl_dev, image_param_out,
922 &surface->isl, &view);
923 }
924 }
925
926 VkResult
927 anv_CreateImageView(VkDevice _device,
928 const VkImageViewCreateInfo *pCreateInfo,
929 const VkAllocationCallbacks *pAllocator,
930 VkImageView *pView)
931 {
932 ANV_FROM_HANDLE(anv_device, device, _device);
933 ANV_FROM_HANDLE(anv_image, image, pCreateInfo->image);
934 struct anv_image_view *iview;
935
936 iview = vk_zalloc2(&device->alloc, pAllocator, sizeof(*iview), 8,
937 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
938 if (iview == NULL)
939 return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
940
941 const VkImageSubresourceRange *range = &pCreateInfo->subresourceRange;
942
943 assert(range->layerCount > 0);
944 assert(range->baseMipLevel < image->levels);
945
946 const VkImageViewUsageCreateInfoKHR *usage_info =
947 vk_find_struct_const(pCreateInfo, IMAGE_VIEW_USAGE_CREATE_INFO_KHR);
948 VkImageUsageFlags view_usage = usage_info ? usage_info->usage : image->usage;
949 /* View usage should be a subset of image usage */
950 assert((view_usage & ~image->usage) == 0);
951 assert(view_usage & (VK_IMAGE_USAGE_SAMPLED_BIT |
952 VK_IMAGE_USAGE_STORAGE_BIT |
953 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
954 VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT |
955 VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT));
956
957 switch (image->type) {
958 default:
959 unreachable("bad VkImageType");
960 case VK_IMAGE_TYPE_1D:
961 case VK_IMAGE_TYPE_2D:
962 assert(range->baseArrayLayer + anv_get_layerCount(image, range) - 1 <= image->array_size);
963 break;
964 case VK_IMAGE_TYPE_3D:
965 assert(range->baseArrayLayer + anv_get_layerCount(image, range) - 1
966 <= anv_minify(image->extent.depth, range->baseMipLevel));
967 break;
968 }
969
970 iview->image = image;
971
972 iview->aspect_mask = pCreateInfo->subresourceRange.aspectMask;
973 iview->vk_format = pCreateInfo->format;
974
975 struct anv_format_plane format =
976 anv_get_format_plane(&device->info, pCreateInfo->format,
977 range->aspectMask == (VK_IMAGE_ASPECT_DEPTH_BIT |
978 VK_IMAGE_ASPECT_STENCIL_BIT) ?
979 VK_IMAGE_ASPECT_DEPTH_BIT : range->aspectMask,
980 image->tiling);
981
982 iview->isl = (struct isl_view) {
983 .format = format.isl_format,
984 .base_level = range->baseMipLevel,
985 .levels = anv_get_levelCount(image, range),
986 .base_array_layer = range->baseArrayLayer,
987 .array_len = anv_get_layerCount(image, range),
988 .swizzle = {
989 .r = remap_swizzle(pCreateInfo->components.r,
990 VK_COMPONENT_SWIZZLE_R, format.swizzle),
991 .g = remap_swizzle(pCreateInfo->components.g,
992 VK_COMPONENT_SWIZZLE_G, format.swizzle),
993 .b = remap_swizzle(pCreateInfo->components.b,
994 VK_COMPONENT_SWIZZLE_B, format.swizzle),
995 .a = remap_swizzle(pCreateInfo->components.a,
996 VK_COMPONENT_SWIZZLE_A, format.swizzle),
997 },
998 };
999
1000 iview->extent = (VkExtent3D) {
1001 .width = anv_minify(image->extent.width , range->baseMipLevel),
1002 .height = anv_minify(image->extent.height, range->baseMipLevel),
1003 .depth = anv_minify(image->extent.depth , range->baseMipLevel),
1004 };
1005
1006 if (pCreateInfo->viewType == VK_IMAGE_VIEW_TYPE_3D) {
1007 iview->isl.base_array_layer = 0;
1008 iview->isl.array_len = iview->extent.depth;
1009 }
1010
1011 if (pCreateInfo->viewType == VK_IMAGE_VIEW_TYPE_CUBE ||
1012 pCreateInfo->viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) {
1013 iview->isl.usage = ISL_SURF_USAGE_CUBE_BIT;
1014 } else {
1015 iview->isl.usage = 0;
1016 }
1017
1018 /* Input attachment surfaces for color are allocated and filled
1019 * out at BeginRenderPass time because they need compression information.
1020 * Compression is not yet enabled for depth textures and stencil doesn't
1021 * allow compression so we can just use the texture surface state from the
1022 * view.
1023 */
1024 if (view_usage & VK_IMAGE_USAGE_SAMPLED_BIT ||
1025 (view_usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT &&
1026 !(iview->aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT))) {
1027 iview->optimal_sampler_surface_state.state = alloc_surface_state(device);
1028 iview->general_sampler_surface_state.state = alloc_surface_state(device);
1029
1030 enum isl_aux_usage general_aux_usage =
1031 anv_layout_to_aux_usage(&device->info, image, iview->aspect_mask,
1032 VK_IMAGE_LAYOUT_GENERAL);
1033 enum isl_aux_usage optimal_aux_usage =
1034 anv_layout_to_aux_usage(&device->info, image, iview->aspect_mask,
1035 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
1036
1037 anv_image_fill_surface_state(device, image, iview->aspect_mask,
1038 &iview->isl, ISL_SURF_USAGE_TEXTURE_BIT,
1039 optimal_aux_usage, NULL,
1040 ANV_IMAGE_VIEW_STATE_TEXTURE_OPTIMAL,
1041 &iview->optimal_sampler_surface_state,
1042 NULL);
1043
1044 anv_image_fill_surface_state(device, image, iview->aspect_mask,
1045 &iview->isl, ISL_SURF_USAGE_TEXTURE_BIT,
1046 general_aux_usage, NULL,
1047 0,
1048 &iview->general_sampler_surface_state,
1049 NULL);
1050 }
1051
1052 /* NOTE: This one needs to go last since it may stomp isl_view.format */
1053 if (view_usage & VK_IMAGE_USAGE_STORAGE_BIT) {
1054 iview->storage_surface_state.state = alloc_surface_state(device);
1055 iview->writeonly_storage_surface_state.state = alloc_surface_state(device);
1056
1057 anv_image_fill_surface_state(device, image, iview->aspect_mask,
1058 &iview->isl, ISL_SURF_USAGE_STORAGE_BIT,
1059 ISL_AUX_USAGE_NONE, NULL,
1060 0,
1061 &iview->storage_surface_state,
1062 &iview->storage_image_param);
1063
1064 anv_image_fill_surface_state(device, image, iview->aspect_mask,
1065 &iview->isl, ISL_SURF_USAGE_STORAGE_BIT,
1066 ISL_AUX_USAGE_NONE, NULL,
1067 ANV_IMAGE_VIEW_STATE_STORAGE_WRITE_ONLY,
1068 &iview->writeonly_storage_surface_state,
1069 NULL);
1070 }
1071
1072 *pView = anv_image_view_to_handle(iview);
1073
1074 return VK_SUCCESS;
1075 }
1076
1077 void
1078 anv_DestroyImageView(VkDevice _device, VkImageView _iview,
1079 const VkAllocationCallbacks *pAllocator)
1080 {
1081 ANV_FROM_HANDLE(anv_device, device, _device);
1082 ANV_FROM_HANDLE(anv_image_view, iview, _iview);
1083
1084 if (!iview)
1085 return;
1086
1087 if (iview->optimal_sampler_surface_state.state.alloc_size > 0) {
1088 anv_state_pool_free(&device->surface_state_pool,
1089 iview->optimal_sampler_surface_state.state);
1090 }
1091
1092 if (iview->general_sampler_surface_state.state.alloc_size > 0) {
1093 anv_state_pool_free(&device->surface_state_pool,
1094 iview->general_sampler_surface_state.state);
1095 }
1096
1097 if (iview->storage_surface_state.state.alloc_size > 0) {
1098 anv_state_pool_free(&device->surface_state_pool,
1099 iview->storage_surface_state.state);
1100 }
1101
1102 if (iview->writeonly_storage_surface_state.state.alloc_size > 0) {
1103 anv_state_pool_free(&device->surface_state_pool,
1104 iview->writeonly_storage_surface_state.state);
1105 }
1106
1107 vk_free2(&device->alloc, pAllocator, iview);
1108 }
1109
1110
1111 VkResult
1112 anv_CreateBufferView(VkDevice _device,
1113 const VkBufferViewCreateInfo *pCreateInfo,
1114 const VkAllocationCallbacks *pAllocator,
1115 VkBufferView *pView)
1116 {
1117 ANV_FROM_HANDLE(anv_device, device, _device);
1118 ANV_FROM_HANDLE(anv_buffer, buffer, pCreateInfo->buffer);
1119 struct anv_buffer_view *view;
1120
1121 view = vk_alloc2(&device->alloc, pAllocator, sizeof(*view), 8,
1122 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
1123 if (!view)
1124 return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
1125
1126 /* TODO: Handle the format swizzle? */
1127
1128 view->format = anv_get_isl_format(&device->info, pCreateInfo->format,
1129 VK_IMAGE_ASPECT_COLOR_BIT,
1130 VK_IMAGE_TILING_LINEAR);
1131 const uint32_t format_bs = isl_format_get_layout(view->format)->bpb / 8;
1132 view->bo = buffer->bo;
1133 view->offset = buffer->offset + pCreateInfo->offset;
1134 view->range = anv_buffer_get_range(buffer, pCreateInfo->offset,
1135 pCreateInfo->range);
1136 view->range = align_down_npot_u32(view->range, format_bs);
1137
1138 if (buffer->usage & VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT) {
1139 view->surface_state = alloc_surface_state(device);
1140
1141 anv_fill_buffer_surface_state(device, view->surface_state,
1142 view->format,
1143 view->offset, view->range, format_bs);
1144 } else {
1145 view->surface_state = (struct anv_state){ 0 };
1146 }
1147
1148 if (buffer->usage & VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT) {
1149 view->storage_surface_state = alloc_surface_state(device);
1150 view->writeonly_storage_surface_state = alloc_surface_state(device);
1151
1152 enum isl_format storage_format =
1153 isl_has_matching_typed_storage_image_format(&device->info,
1154 view->format) ?
1155 isl_lower_storage_image_format(&device->info, view->format) :
1156 ISL_FORMAT_RAW;
1157
1158 anv_fill_buffer_surface_state(device, view->storage_surface_state,
1159 storage_format,
1160 view->offset, view->range,
1161 (storage_format == ISL_FORMAT_RAW ? 1 :
1162 isl_format_get_layout(storage_format)->bpb / 8));
1163
1164 /* Write-only accesses should use the original format. */
1165 anv_fill_buffer_surface_state(device, view->writeonly_storage_surface_state,
1166 view->format,
1167 view->offset, view->range,
1168 isl_format_get_layout(view->format)->bpb / 8);
1169
1170 isl_buffer_fill_image_param(&device->isl_dev,
1171 &view->storage_image_param,
1172 view->format, view->range);
1173 } else {
1174 view->storage_surface_state = (struct anv_state){ 0 };
1175 view->writeonly_storage_surface_state = (struct anv_state){ 0 };
1176 }
1177
1178 *pView = anv_buffer_view_to_handle(view);
1179
1180 return VK_SUCCESS;
1181 }
1182
1183 void
1184 anv_DestroyBufferView(VkDevice _device, VkBufferView bufferView,
1185 const VkAllocationCallbacks *pAllocator)
1186 {
1187 ANV_FROM_HANDLE(anv_device, device, _device);
1188 ANV_FROM_HANDLE(anv_buffer_view, view, bufferView);
1189
1190 if (!view)
1191 return;
1192
1193 if (view->surface_state.alloc_size > 0)
1194 anv_state_pool_free(&device->surface_state_pool,
1195 view->surface_state);
1196
1197 if (view->storage_surface_state.alloc_size > 0)
1198 anv_state_pool_free(&device->surface_state_pool,
1199 view->storage_surface_state);
1200
1201 if (view->writeonly_storage_surface_state.alloc_size > 0)
1202 anv_state_pool_free(&device->surface_state_pool,
1203 view->writeonly_storage_surface_state);
1204
1205 vk_free2(&device->alloc, pAllocator, view);
1206 }
1207
1208 const struct anv_surface *
1209 anv_image_get_surface_for_aspect_mask(const struct anv_image *image,
1210 VkImageAspectFlags aspect_mask)
1211 {
1212 switch (aspect_mask) {
1213 case VK_IMAGE_ASPECT_COLOR_BIT:
1214 assert(image->aspects == VK_IMAGE_ASPECT_COLOR_BIT);
1215 return &image->color_surface;
1216 case VK_IMAGE_ASPECT_DEPTH_BIT:
1217 assert(image->aspects & VK_IMAGE_ASPECT_DEPTH_BIT);
1218 return &image->depth_surface;
1219 case VK_IMAGE_ASPECT_STENCIL_BIT:
1220 assert(image->aspects & VK_IMAGE_ASPECT_STENCIL_BIT);
1221 return &image->stencil_surface;
1222 case VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT:
1223 /* FINISHME: The Vulkan spec (git a511ba2) requires support for
1224 * combined depth stencil formats. Specifically, it states:
1225 *
1226 * At least one of ename:VK_FORMAT_D24_UNORM_S8_UINT or
1227 * ename:VK_FORMAT_D32_SFLOAT_S8_UINT must be supported.
1228 *
1229 * Image views with both depth and stencil aspects are only valid for
1230 * render target attachments, in which case
1231 * cmd_buffer_emit_depth_stencil() will pick out both the depth and
1232 * stencil surfaces from the underlying surface.
1233 */
1234 if (image->aspects & VK_IMAGE_ASPECT_DEPTH_BIT) {
1235 return &image->depth_surface;
1236 } else {
1237 assert(image->aspects == VK_IMAGE_ASPECT_STENCIL_BIT);
1238 return &image->stencil_surface;
1239 }
1240 default:
1241 unreachable("image does not have aspect");
1242 return NULL;
1243 }
1244 }