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