vk: Add SKL support
[mesa.git] / src / 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
30 #include "anv_private.h"
31
32 /* FIXME: We shouldn't be using the actual hardware enum values here. They
33 * change across gens. Once we get that fixed, this include needs to go.
34 */
35 #include "gen8_pack.h"
36
37 static const uint8_t anv_halign[] = {
38 [4] = HALIGN4,
39 [8] = HALIGN8,
40 [16] = HALIGN16,
41 };
42
43 static const uint8_t anv_valign[] = {
44 [4] = VALIGN4,
45 [8] = VALIGN8,
46 [16] = VALIGN16,
47 };
48
49 static const uint8_t anv_surf_type_from_image_type[] = {
50 [VK_IMAGE_TYPE_1D] = SURFTYPE_1D,
51 [VK_IMAGE_TYPE_2D] = SURFTYPE_2D,
52 [VK_IMAGE_TYPE_3D] = SURFTYPE_3D,
53 };
54
55 static const struct anv_image_view_info
56 anv_image_view_info_table[] = {
57 #define INFO(s, ...) { .surface_type = s, __VA_ARGS__ }
58 [VK_IMAGE_VIEW_TYPE_1D] = INFO(SURFTYPE_1D),
59 [VK_IMAGE_VIEW_TYPE_2D] = INFO(SURFTYPE_2D),
60 [VK_IMAGE_VIEW_TYPE_3D] = INFO(SURFTYPE_3D),
61 [VK_IMAGE_VIEW_TYPE_CUBE] = INFO(SURFTYPE_CUBE, .is_cube = 1),
62 [VK_IMAGE_VIEW_TYPE_1D_ARRAY] = INFO(SURFTYPE_1D, .is_array = 1),
63 [VK_IMAGE_VIEW_TYPE_2D_ARRAY] = INFO(SURFTYPE_2D, .is_array = 1),
64 [VK_IMAGE_VIEW_TYPE_CUBE_ARRAY] = INFO(SURFTYPE_CUBE, .is_array = 1, .is_cube = 1),
65 #undef INFO
66 };
67
68 struct anv_image_view_info
69 anv_image_view_info_for_vk_image_view_type(VkImageViewType type)
70 {
71 return anv_image_view_info_table[type];
72 }
73
74 static const struct anv_surf_type_limits {
75 int32_t width;
76 int32_t height;
77 int32_t depth;
78 } anv_surf_type_limits[] = {
79 [SURFTYPE_1D] = {16384, 1, 2048},
80 [SURFTYPE_2D] = {16384, 16384, 2048},
81 [SURFTYPE_3D] = {2048, 2048, 2048},
82 [SURFTYPE_CUBE] = {16384, 16384, 340},
83 [SURFTYPE_BUFFER] = {128, 16384, 64},
84 [SURFTYPE_STRBUF] = {128, 16384, 64},
85 };
86
87 static const struct anv_tile_info {
88 /**
89 * Alignment for RENDER_SURFACE_STATE.SurfaceBaseAddress.
90 *
91 * To simplify calculations, the alignments defined in the table are
92 * sometimes larger than required. For example, Skylake requires that X and
93 * Y tiled buffers be aligned to 4K, but Broadwell permits smaller
94 * alignment. We choose 4K to accomodate both chipsets. The alignment of
95 * a linear buffer depends on its element type and usage. Linear depth
96 * buffers have the largest alignment, 64B, so we choose that for all linear
97 * buffers.
98 */
99 uint32_t surface_alignment;
100 } anv_tile_info_table[] = {
101 [ISL_TILING_LINEAR] = { 64 },
102 [ISL_TILING_X] = { 4096 },
103 [ISL_TILING_Y] = { 4096 },
104 [ISL_TILING_Yf] = { 4096 },
105 [ISL_TILING_Ys] = { 4096 },
106 [ISL_TILING_W] = { 4096 },
107 };
108
109 static enum isl_tiling
110 anv_image_choose_tiling(const struct anv_image_create_info *anv_info)
111 {
112 if (anv_info->force_tiling)
113 return anv_info->tiling;
114
115 /* The Sandybridge PRM says that the stencil buffer "is supported
116 * only in Tile W memory".
117 */
118
119 switch (anv_info->vk_info->tiling) {
120 case VK_IMAGE_TILING_LINEAR:
121 assert(anv_info->vk_info->format != VK_FORMAT_S8_UINT);
122 return ISL_TILING_LINEAR;
123 case VK_IMAGE_TILING_OPTIMAL:
124 if (unlikely(anv_info->vk_info->format == VK_FORMAT_S8_UINT)) {
125 return ISL_TILING_W;
126 } else {
127 return ISL_TILING_Y;
128 }
129 default:
130 assert(!"bad VKImageTiling");
131 return ISL_TILING_LINEAR;
132 }
133 }
134
135
136 /**
137 * The \a format argument is required and overrides any format in
138 * struct anv_image_create_info.
139 */
140 static VkResult
141 anv_image_make_surface(const struct anv_device *dev,
142 const struct anv_image_create_info *create_info,
143 const struct anv_format *format,
144 uint64_t *inout_image_size,
145 uint32_t *inout_image_alignment,
146 struct anv_surface *out_surface)
147 {
148 /* See RENDER_SURFACE_STATE.SurfaceQPitch */
149 static const uint16_t min_qpitch UNUSED = 0x4;
150 static const uint16_t max_qpitch UNUSED = 0x1ffc;
151
152 const VkExtent3D *restrict extent = &create_info->vk_info->extent;
153 const uint32_t levels = create_info->vk_info->mipLevels;
154 const uint32_t array_size = create_info->vk_info->arraySize;
155 const enum isl_tiling tiling = anv_image_choose_tiling(create_info);
156
157 const struct anv_tile_info *tile_info =
158 &anv_tile_info_table[tiling];
159
160 const uint32_t bs = format->isl_layout->bs;
161 const uint32_t bw = format->isl_layout->bw;
162 const uint32_t bh = format->isl_layout->bh;
163
164 struct isl_extent2d tile_extent;
165 isl_tiling_get_extent(&dev->isl_dev, tiling, bs, &tile_extent);
166
167 const uint32_t i = MAX(4, bw); /* FINISHME: Stop hardcoding subimage alignment */
168 const uint32_t j = MAX(4, bh); /* FINISHME: Stop hardcoding subimage alignment */
169 assert(i == 4 || i == 8 || i == 16);
170 assert(j == 4 || j == 8 || j == 16);
171
172 uint16_t qpitch = min_qpitch;
173 uint32_t mt_width = 0;
174 uint32_t mt_height = 0;
175
176 switch (create_info->vk_info->imageType) {
177 case VK_IMAGE_TYPE_1D:
178 /* From the Broadwell PRM >> Memory Views >> Common Surface Formats >>
179 * Surface Layout >> 1D Surfaces:
180 *
181 * One-dimensional surfaces are identical to 2D surfaces with height of one.
182 *
183 * So fallthrough...
184 */
185 case VK_IMAGE_TYPE_2D: {
186 const uint32_t w0 = align_u32(extent->width, i);
187 const uint32_t h0 = align_u32(extent->height, j);
188
189 if (levels == 1 && array_size == 1) {
190 qpitch = min_qpitch;
191 mt_width = w0;
192 mt_height = h0;
193 } else {
194 uint32_t w1 = align_u32(anv_minify(extent->width, 1), i);
195 uint32_t h1 = align_u32(anv_minify(extent->height, 1), j);
196 uint32_t w2 = align_u32(anv_minify(extent->width, 2), i);
197
198 /* The QPitch equation is found in the Broadwell PRM >> Volume 5: Memory
199 * Views >> Common Surface Formats >> Surface Layout >> 2D Surfaces >>
200 * Surface Arrays >> For All Surface Other Than Separate Stencil Buffer:
201 */
202 assert(bh ==1 || bh == 4);
203 qpitch = (h0 + h1 + 11 * j) / bh;
204 mt_width = MAX(w0, w1 + w2);
205 mt_height = array_size * qpitch;
206 }
207 break;
208 }
209 case VK_IMAGE_TYPE_3D:
210 /* The layout of 3D surfaces is described by the Broadwell PRM >>
211 * Volume 5: Memory Views >> Common Surface Formats >> Surface Layout >>
212 * 3D Surfaces.
213 */
214 for (uint32_t l = 0; l < levels; ++l) {
215 const uint32_t w_l = align_u32(anv_minify(extent->width, l), i);
216 const uint32_t h_l = align_u32(anv_minify(extent->height, l), j);
217 const uint32_t d_l = anv_minify(extent->depth, l);
218
219 const uint32_t max_layers_horiz = MIN(d_l, 1u << l);
220 const uint32_t max_layers_vert = align_u32(d_l, 1u << l) / (1u << l);
221
222 mt_width = MAX(mt_width, w_l * max_layers_horiz);
223 mt_height += h_l * max_layers_vert;
224 }
225 break;
226 default:
227 unreachable(!"bad VkImageType");
228 }
229
230 assert(qpitch >= min_qpitch);
231 if (qpitch > max_qpitch) {
232 anv_loge("image qpitch > 0x%x\n", max_qpitch);
233 return vk_error(VK_ERROR_OUT_OF_DEVICE_MEMORY);
234 }
235
236 /* From the Broadwell PRM, RENDER_SURFACE_STATE.SurfaceQpitch:
237 *
238 * This field must be set an integer multiple of the Surface Vertical
239 * Alignment.
240 */
241 assert(anv_is_aligned(qpitch, j));
242
243 uint32_t stride = align_u32(mt_width * bs / bw, tile_extent.width);
244 if (create_info->stride > 0)
245 stride = create_info->stride;
246
247 /* The padding requirement is found in the Broadwell PRM >> Volume 5: Memory
248 * Views >> Common Surface Formats >> Surface Padding Requirements >>
249 * Sampling Engine Surfaces >> Buffer Padding Requirements:
250 */
251 const uint32_t mem_rows = align_u32(mt_height / bh, 2 * bh);
252 const uint32_t size = stride * align_u32(mem_rows, tile_extent.height);
253 const uint32_t offset = align_u32(*inout_image_size,
254 tile_info->surface_alignment);
255
256 *inout_image_size = offset + size;
257 *inout_image_alignment = MAX(*inout_image_alignment,
258 tile_info->surface_alignment);
259
260 *out_surface = (struct anv_surface) {
261 .offset = offset,
262 .stride = stride,
263 .tiling = tiling,
264 .qpitch = qpitch,
265 .h_align = i,
266 .v_align = j,
267 };
268
269 return VK_SUCCESS;
270 }
271
272 static VkImageUsageFlags
273 anv_image_get_full_usage(const VkImageCreateInfo *info)
274 {
275 VkImageUsageFlags usage = info->usage;
276
277 if (usage & VK_IMAGE_USAGE_TRANSFER_SOURCE_BIT) {
278 /* Meta will transfer from the image by binding it as a texture. */
279 usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
280 }
281
282 if (usage & VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT) {
283 /* Meta will transfer to the image by binding it as a color attachment,
284 * even if the image format is not a color format.
285 */
286 usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
287 }
288
289 return usage;
290 }
291
292 VkResult
293 anv_image_create(VkDevice _device,
294 const struct anv_image_create_info *create_info,
295 VkImage *pImage)
296 {
297 ANV_FROM_HANDLE(anv_device, device, _device);
298 const VkImageCreateInfo *pCreateInfo = create_info->vk_info;
299 const VkExtent3D *restrict extent = &pCreateInfo->extent;
300 struct anv_image *image = NULL;
301 VkResult r;
302
303 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO);
304
305 anv_assert(pCreateInfo->mipLevels > 0);
306 anv_assert(pCreateInfo->arraySize > 0);
307 anv_assert(pCreateInfo->samples == 1);
308 anv_assert(pCreateInfo->extent.width > 0);
309 anv_assert(pCreateInfo->extent.height > 0);
310 anv_assert(pCreateInfo->extent.depth > 0);
311
312 /* TODO(chadv): How should we validate inputs? */
313 const uint8_t surf_type =
314 anv_surf_type_from_image_type[pCreateInfo->imageType];
315
316 const struct anv_surf_type_limits *limits =
317 &anv_surf_type_limits[surf_type];
318
319 /* Errors should be caught by VkImageFormatProperties. */
320 assert(extent->width <= limits->width);
321 assert(extent->height <= limits->height);
322 assert(extent->depth <= limits->depth);
323
324 image = anv_device_alloc(device, sizeof(*image), 8,
325 VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
326 if (!image)
327 return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
328
329 memset(image, 0, sizeof(*image));
330 image->type = pCreateInfo->imageType;
331 image->extent = pCreateInfo->extent;
332 image->format = anv_format_for_vk_format(pCreateInfo->format);
333 image->levels = pCreateInfo->mipLevels;
334 image->array_size = pCreateInfo->arraySize;
335 image->usage = anv_image_get_full_usage(pCreateInfo);
336 image->surface_type = surf_type;
337
338 if (image->usage & (VK_IMAGE_USAGE_SAMPLED_BIT |
339 VK_IMAGE_USAGE_STORAGE_BIT)) {
340 image->needs_nonrt_surface_state = true;
341 }
342
343 if (image->usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
344 image->needs_color_rt_surface_state = true;
345 }
346
347 if (likely(anv_format_is_color(image->format))) {
348 r = anv_image_make_surface(device, create_info, image->format,
349 &image->size, &image->alignment,
350 &image->color_surface);
351 if (r != VK_SUCCESS)
352 goto fail;
353 } else {
354 if (image->format->depth_format) {
355 r = anv_image_make_surface(device, create_info, image->format,
356 &image->size, &image->alignment,
357 &image->depth_surface);
358 if (r != VK_SUCCESS)
359 goto fail;
360 }
361
362 if (image->format->has_stencil) {
363 r = anv_image_make_surface(device, create_info, anv_format_s8_uint,
364 &image->size, &image->alignment,
365 &image->stencil_surface);
366 if (r != VK_SUCCESS)
367 goto fail;
368 }
369 }
370
371 *pImage = anv_image_to_handle(image);
372
373 return VK_SUCCESS;
374
375 fail:
376 if (image)
377 anv_device_free(device, image);
378
379 return r;
380 }
381
382 VkResult
383 anv_CreateImage(VkDevice device,
384 const VkImageCreateInfo *pCreateInfo,
385 VkImage *pImage)
386 {
387 return anv_image_create(device,
388 &(struct anv_image_create_info) {
389 .vk_info = pCreateInfo,
390 },
391 pImage);
392 }
393
394 void
395 anv_DestroyImage(VkDevice _device, VkImage _image)
396 {
397 ANV_FROM_HANDLE(anv_device, device, _device);
398
399 anv_device_free(device, anv_image_from_handle(_image));
400 }
401
402 static void
403 anv_surface_get_subresource_layout(struct anv_image *image,
404 struct anv_surface *surface,
405 const VkImageSubresource *subresource,
406 VkSubresourceLayout *layout)
407 {
408 /* If we are on a non-zero mip level or array slice, we need to
409 * calculate a real offset.
410 */
411 anv_assert(subresource->mipLevel == 0);
412 anv_assert(subresource->arrayLayer == 0);
413
414 layout->offset = surface->offset;
415 layout->rowPitch = surface->stride;
416 layout->depthPitch = surface->qpitch;
417
418 /* FINISHME: We really shouldn't be doing this calculation here */
419 if (image->array_size > 1)
420 layout->size = surface->qpitch * image->array_size;
421 else
422 layout->size = surface->stride * image->extent.height;
423 }
424
425 VkResult anv_GetImageSubresourceLayout(
426 VkDevice device,
427 VkImage _image,
428 const VkImageSubresource* pSubresource,
429 VkSubresourceLayout* pLayout)
430 {
431 ANV_FROM_HANDLE(anv_image, image, _image);
432
433 switch (pSubresource->aspect) {
434 case VK_IMAGE_ASPECT_COLOR:
435 anv_surface_get_subresource_layout(image, &image->color_surface,
436 pSubresource, pLayout);
437 break;
438 case VK_IMAGE_ASPECT_DEPTH:
439 anv_surface_get_subresource_layout(image, &image->depth_surface,
440 pSubresource, pLayout);
441 break;
442 case VK_IMAGE_ASPECT_STENCIL:
443 anv_surface_get_subresource_layout(image, &image->stencil_surface,
444 pSubresource, pLayout);
445 break;
446 default:
447 return vk_error(VK_UNSUPPORTED);
448 }
449
450 return VK_SUCCESS;
451 }
452
453 VkResult
454 anv_validate_CreateImageView(VkDevice _device,
455 const VkImageViewCreateInfo *pCreateInfo,
456 VkImageView *pView)
457 {
458 ANV_FROM_HANDLE(anv_image, image, pCreateInfo->image);
459 const VkImageSubresourceRange *subresource;
460 const struct anv_image_view_info *view_info;
461 const struct anv_format *view_format_info;
462
463 /* Validate structure type before dereferencing it. */
464 assert(pCreateInfo);
465 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO);
466 subresource = &pCreateInfo->subresourceRange;
467
468 /* Validate viewType is in range before using it. */
469 assert(pCreateInfo->viewType >= VK_IMAGE_VIEW_TYPE_BEGIN_RANGE);
470 assert(pCreateInfo->viewType <= VK_IMAGE_VIEW_TYPE_END_RANGE);
471 view_info = &anv_image_view_info_table[pCreateInfo->viewType];
472
473 /* Validate format is in range before using it. */
474 assert(pCreateInfo->format >= VK_FORMAT_BEGIN_RANGE);
475 assert(pCreateInfo->format <= VK_FORMAT_END_RANGE);
476 view_format_info = anv_format_for_vk_format(pCreateInfo->format);
477
478 /* Validate channel swizzles. */
479 assert(pCreateInfo->channels.r >= VK_CHANNEL_SWIZZLE_BEGIN_RANGE);
480 assert(pCreateInfo->channels.r <= VK_CHANNEL_SWIZZLE_END_RANGE);
481 assert(pCreateInfo->channels.g >= VK_CHANNEL_SWIZZLE_BEGIN_RANGE);
482 assert(pCreateInfo->channels.g <= VK_CHANNEL_SWIZZLE_END_RANGE);
483 assert(pCreateInfo->channels.b >= VK_CHANNEL_SWIZZLE_BEGIN_RANGE);
484 assert(pCreateInfo->channels.b <= VK_CHANNEL_SWIZZLE_END_RANGE);
485 assert(pCreateInfo->channels.a >= VK_CHANNEL_SWIZZLE_BEGIN_RANGE);
486 assert(pCreateInfo->channels.a <= VK_CHANNEL_SWIZZLE_END_RANGE);
487
488 /* Validate subresource. */
489 assert(subresource->aspectMask != 0);
490 assert(subresource->mipLevels > 0);
491 assert(subresource->arraySize > 0);
492 assert(subresource->baseMipLevel < image->levels);
493 assert(subresource->baseMipLevel + subresource->mipLevels <= image->levels);
494 assert(subresource->baseArrayLayer < image->array_size);
495 assert(subresource->baseArrayLayer + subresource->arraySize <= image->array_size);
496 assert(pView);
497
498 if (view_info->is_cube) {
499 assert(subresource->baseArrayLayer % 6 == 0);
500 assert(subresource->arraySize % 6 == 0);
501 }
502
503 const VkImageAspectFlags ds_flags = VK_IMAGE_ASPECT_DEPTH_BIT
504 | VK_IMAGE_ASPECT_STENCIL_BIT;
505
506 /* Validate format. */
507 if (subresource->aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) {
508 assert(subresource->aspectMask == VK_IMAGE_ASPECT_COLOR_BIT);
509 assert(!image->format->depth_format);
510 assert(!image->format->has_stencil);
511 assert(!view_format_info->depth_format);
512 assert(!view_format_info->has_stencil);
513 assert(view_format_info->isl_layout->bs ==
514 image->format->isl_layout->bs);
515 } else if (subresource->aspectMask & ds_flags) {
516 assert((subresource->aspectMask & ~ds_flags) == 0);
517
518 if (subresource->aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) {
519 assert(image->format->depth_format);
520 assert(view_format_info->depth_format);
521 assert(view_format_info->isl_layout->bs ==
522 image->format->isl_layout->bs);
523 }
524
525 if (subresource->aspectMask & VK_IMAGE_ASPECT_STENCIL) {
526 /* FINISHME: Is it legal to have an R8 view of S8? */
527 assert(image->format->has_stencil);
528 assert(view_format_info->has_stencil);
529 }
530 } else {
531 assert(!"bad VkImageSubresourceRange::aspectFlags");
532 }
533
534 return anv_CreateImageView(_device, pCreateInfo, pView);
535 }
536
537 void
538 anv_image_view_init(struct anv_image_view *iview,
539 struct anv_device *device,
540 const VkImageViewCreateInfo* pCreateInfo,
541 struct anv_cmd_buffer *cmd_buffer)
542 {
543 ANV_FROM_HANDLE(anv_image, image, pCreateInfo->image);
544 const VkImageSubresourceRange *range = &pCreateInfo->subresourceRange;
545
546 assert(range->arraySize > 0);
547 assert(range->baseMipLevel < image->levels);
548 assert(image->usage & (VK_IMAGE_USAGE_SAMPLED_BIT |
549 VK_IMAGE_USAGE_STORAGE_BIT |
550 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
551 VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT));
552
553 switch (image->type) {
554 default:
555 unreachable("bad VkImageType");
556 case VK_IMAGE_TYPE_1D:
557 case VK_IMAGE_TYPE_2D:
558 assert(range->baseArrayLayer + range->arraySize - 1 <= image->array_size);
559 break;
560 case VK_IMAGE_TYPE_3D:
561 assert(range->baseArrayLayer + range->arraySize - 1
562 <= anv_minify(image->extent.depth, range->baseMipLevel));
563 break;
564 }
565
566 switch (device->info.gen) {
567 case 7:
568 if (device->info.is_haswell)
569 gen75_image_view_init(iview, device, pCreateInfo, cmd_buffer);
570 else
571 gen7_image_view_init(iview, device, pCreateInfo, cmd_buffer);
572 break;
573 case 8:
574 gen8_image_view_init(iview, device, pCreateInfo, cmd_buffer);
575 break;
576 case 9:
577 gen9_image_view_init(iview, device, pCreateInfo, cmd_buffer);
578 break;
579 default:
580 unreachable("unsupported gen\n");
581 }
582 }
583
584 VkResult
585 anv_CreateImageView(VkDevice _device,
586 const VkImageViewCreateInfo *pCreateInfo,
587 VkImageView *pView)
588 {
589 ANV_FROM_HANDLE(anv_device, device, _device);
590 struct anv_image_view *view;
591
592 view = anv_device_alloc(device, sizeof(*view), 8,
593 VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
594 if (view == NULL)
595 return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
596
597 anv_image_view_init(view, device, pCreateInfo, NULL);
598
599 *pView = anv_image_view_to_handle(view);
600
601 return VK_SUCCESS;
602 }
603
604 static void
605 anv_image_view_destroy(struct anv_device *device,
606 struct anv_image_view *iview)
607 {
608 if (iview->image->needs_color_rt_surface_state) {
609 anv_state_pool_free(&device->surface_state_pool,
610 iview->color_rt_surface_state);
611 }
612
613 if (iview->image->needs_nonrt_surface_state) {
614 anv_state_pool_free(&device->surface_state_pool,
615 iview->nonrt_surface_state);
616 }
617
618 anv_device_free(device, iview);
619 }
620
621 void
622 anv_DestroyImageView(VkDevice _device, VkImageView _iview)
623 {
624 ANV_FROM_HANDLE(anv_device, device, _device);
625 ANV_FROM_HANDLE(anv_image_view, iview, _iview);
626
627 anv_image_view_destroy(device, iview);
628 }
629
630 struct anv_surface *
631 anv_image_get_surface_for_aspect_mask(struct anv_image *image, VkImageAspectFlags aspect_mask)
632 {
633 switch (aspect_mask) {
634 case VK_IMAGE_ASPECT_COLOR_BIT:
635 /* Dragons will eat you.
636 *
637 * Meta attaches all destination surfaces as color render targets. Guess
638 * what surface the Meta Dragons really want.
639 */
640 if (image->format->depth_format && image->format->has_stencil) {
641 anv_finishme("combined depth stencil formats");
642 return &image->depth_surface;
643 } else if (image->format->depth_format) {
644 return &image->depth_surface;
645 } else if (image->format->has_stencil) {
646 return &image->stencil_surface;
647 } else {
648 return &image->color_surface;
649 }
650 break;
651 case VK_IMAGE_ASPECT_DEPTH_BIT:
652 assert(image->format->depth_format);
653 return &image->depth_surface;
654 case VK_IMAGE_ASPECT_STENCIL_BIT:
655 assert(image->format->has_stencil);
656 return &image->stencil_surface;
657 case VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT:
658 if (image->format->depth_format && image->format->has_stencil) {
659 /* FINISHME: The Vulkan spec (git a511ba2) requires support for combined
660 * depth stencil formats. Specifically, it states:
661 *
662 * At least one of ename:VK_FORMAT_D24_UNORM_S8_UINT or
663 * ename:VK_FORMAT_D32_SFLOAT_S8_UINT must be supported.
664 */
665 anv_finishme("combined depthstencil aspect");
666 return &image->depth_surface;
667 } else if (image->format->depth_format) {
668 return &image->depth_surface;
669 } else if (image->format->has_stencil) {
670 return &image->stencil_surface;
671 }
672 /* fallthrough */
673 default:
674 unreachable("image does not have aspect");
675 return NULL;
676 }
677 }
678
679 #if 0
680 VkImageAspectFlags aspect_mask = 0;
681 if (format->depth_format)
682 aspect_mask |= VK_IMAGE_ASPECT_DEPTH_BIT;
683 if (format->has_stencil)
684 aspect_mask |= VK_IMAGE_ASPECT_STENCIL_BIT;
685 if (!aspect_mask)
686 aspect_mask |= VK_IMAGE_ASPECT_COLOR_BIT;
687
688 anv_image_view_init(iview, device,
689 &(VkImageViewCreateInfo) {
690 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
691 .image = info->image,
692 .viewType = VK_IMAGE_VIEW_TYPE_2D,
693 .format = info->format,
694 .channels = {
695 .r = VK_CHANNEL_SWIZZLE_R,
696 .g = VK_CHANNEL_SWIZZLE_G,
697 .b = VK_CHANNEL_SWIZZLE_B,
698 .a = VK_CHANNEL_SWIZZLE_A,
699 },
700 .subresourceRange = {
701 .aspectMask = aspect_mask,
702 .baseMipLevel = info->mipLevel,
703 .mipLevels = 1,
704 .baseArrayLayer = info->baseArraySlice,
705 .arraySize = info->arraySize,
706 },
707 },
708 NULL);
709 #endif