2 * Copyright © 2015 Intel Corporation
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:
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
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
32 static const uint8_t anv_halign
[] = {
38 static const uint8_t anv_valign
[] = {
44 static const uint8_t anv_surf_type_from_image_type
[] = {
45 [VK_IMAGE_TYPE_1D
] = SURFTYPE_1D
,
46 [VK_IMAGE_TYPE_2D
] = SURFTYPE_2D
,
47 [VK_IMAGE_TYPE_3D
] = SURFTYPE_3D
,
50 static const uint8_t anv_surf_type_from_image_view_type
[] = {
51 [VK_IMAGE_VIEW_TYPE_1D
] = SURFTYPE_1D
,
52 [VK_IMAGE_VIEW_TYPE_2D
] = SURFTYPE_2D
,
53 [VK_IMAGE_VIEW_TYPE_3D
] = SURFTYPE_3D
,
54 [VK_IMAGE_VIEW_TYPE_CUBE
] = SURFTYPE_CUBE
,
57 static const struct anv_surf_type_limits
{
61 } anv_surf_type_limits
[] = {
62 [SURFTYPE_1D
] = {16384, 0, 2048},
63 [SURFTYPE_2D
] = {16384, 16384, 2048},
64 [SURFTYPE_3D
] = {2048, 2048, 2048},
65 [SURFTYPE_CUBE
] = {16384, 16384, 340},
66 [SURFTYPE_BUFFER
] = {128, 16384, 64},
67 [SURFTYPE_STRBUF
] = {128, 16384, 64},
70 static const struct anv_tile_info
{
75 * Alignment for RENDER_SURFACE_STATE.SurfaceBaseAddress.
77 * To simplify calculations, the alignments defined in the table are
78 * sometimes larger than required. For example, Skylake requires that X and
79 * Y tiled buffers be aligned to 4K, but Broadwell permits smaller
80 * alignment. We choose 4K to accomodate both chipsets. The alignment of
81 * a linear buffer depends on its element type and usage. Linear depth
82 * buffers have the largest alignment, 64B, so we choose that for all linear
85 uint32_t surface_alignment
;
86 } anv_tile_info_table
[] = {
87 [LINEAR
] = { 1, 1, 64 },
88 [XMAJOR
] = { 512, 8, 4096 },
89 [YMAJOR
] = { 128, 32, 4096 },
90 [WMAJOR
] = { 128, 32, 4096 },
94 anv_image_choose_tile_mode(const struct anv_image_create_info
*anv_info
)
96 if (anv_info
->force_tile_mode
)
97 return anv_info
->tile_mode
;
99 if (anv_info
->vk_info
->format
== VK_FORMAT_S8_UINT
)
102 switch (anv_info
->vk_info
->tiling
) {
103 case VK_IMAGE_TILING_LINEAR
:
105 case VK_IMAGE_TILING_OPTIMAL
:
108 assert(!"bad VKImageTiling");
114 anv_image_make_surface(const struct anv_image_create_info
*create_info
,
115 uint64_t *inout_image_size
,
116 uint32_t *inout_image_alignment
,
117 struct anv_surface
*out_surface
)
119 /* See RENDER_SURFACE_STATE.SurfaceQPitch */
120 static const uint16_t min_qpitch UNUSED
= 0x4;
121 static const uint16_t max_qpitch UNUSED
= 0x1ffc;
123 const VkExtent3D
*restrict extent
= &create_info
->vk_info
->extent
;
124 const uint32_t levels
= create_info
->vk_info
->mipLevels
;
125 const uint32_t array_size
= create_info
->vk_info
->arraySize
;
127 const uint8_t tile_mode
= anv_image_choose_tile_mode(create_info
);
129 const struct anv_tile_info
*tile_info
=
130 &anv_tile_info_table
[tile_mode
];
132 const struct anv_format
*format_info
=
133 anv_format_for_vk_format(create_info
->vk_info
->format
);
135 const uint32_t i
= 4; /* FINISHME: Stop hardcoding subimage alignment */
136 const uint32_t j
= 4; /* FINISHME: Stop hardcoding subimage alignment */
137 const uint32_t w0
= align_u32(extent
->width
, i
);
138 const uint32_t h0
= align_u32(extent
->height
, j
);
144 if (levels
== 1 && array_size
== 1) {
149 uint32_t w1
= align_u32(anv_minify(extent
->width
, 1), i
);
150 uint32_t h1
= align_u32(anv_minify(extent
->height
, 1), j
);
151 uint32_t w2
= align_u32(anv_minify(extent
->width
, 2), i
);
153 qpitch
= h0
+ h1
+ 11 * j
;
154 mt_width
= MAX(w0
, w1
+ w2
);
155 mt_height
= array_size
* qpitch
;
158 assert(qpitch
>= min_qpitch
);
159 if (qpitch
> max_qpitch
) {
160 anv_loge("image qpitch > 0x%x\n", max_qpitch
);
161 return vk_error(VK_ERROR_OUT_OF_DEVICE_MEMORY
);
164 /* From the Broadwell PRM, RENDER_SURFACE_STATE.SurfaceQpitch:
166 * This field must be set an integer multiple of the Surface Vertical
169 assert(anv_is_aligned(qpitch
, j
));
171 const uint32_t stride
= align_u32(mt_width
* format_info
->cpp
,
173 const uint32_t size
= stride
* align_u32(mt_height
, tile_info
->height
);
174 const uint32_t offset
= align_u32(*inout_image_size
,
175 tile_info
->surface_alignment
);
177 *inout_image_size
= offset
+ size
;
178 *inout_image_alignment
= MAX(*inout_image_alignment
,
179 tile_info
->surface_alignment
);
181 *out_surface
= (struct anv_surface
) {
184 .tile_mode
= tile_mode
,
194 anv_image_create(VkDevice _device
,
195 const struct anv_image_create_info
*create_info
,
198 struct anv_device
*device
= (struct anv_device
*) _device
;
199 const VkImageCreateInfo
*pCreateInfo
= create_info
->vk_info
;
200 const VkExtent3D
*restrict extent
= &pCreateInfo
->extent
;
201 struct anv_image
*image
= NULL
;
204 assert(pCreateInfo
->sType
== VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO
);
206 /* XXX: We don't handle any of these */
207 anv_assert(pCreateInfo
->imageType
== VK_IMAGE_TYPE_2D
);
208 anv_assert(pCreateInfo
->mipLevels
> 0);
209 anv_assert(pCreateInfo
->arraySize
> 0);
210 anv_assert(pCreateInfo
->samples
== 1);
211 anv_assert(pCreateInfo
->extent
.width
> 0);
212 anv_assert(pCreateInfo
->extent
.height
> 0);
213 anv_assert(pCreateInfo
->extent
.depth
> 0);
215 /* TODO(chadv): How should we validate inputs? */
216 const uint8_t surf_type
=
217 anv_surf_type_from_image_type
[pCreateInfo
->imageType
];
219 const struct anv_surf_type_limits
*limits
=
220 &anv_surf_type_limits
[surf_type
];
222 if (extent
->width
> limits
->width
||
223 extent
->height
> limits
->height
||
224 extent
->depth
> limits
->depth
) {
225 /* TODO(chadv): What is the correct error? */
226 anv_loge("image extent is too large");
227 return vk_error(VK_ERROR_INVALID_MEMORY_SIZE
);
230 const struct anv_format
*format_info
=
231 anv_format_for_vk_format(pCreateInfo
->format
);
233 image
= anv_device_alloc(device
, sizeof(*image
), 8,
234 VK_SYSTEM_ALLOC_TYPE_API_OBJECT
);
236 return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY
);
238 memset(image
, 0, sizeof(*image
));
239 image
->type
= pCreateInfo
->imageType
;
240 image
->extent
= pCreateInfo
->extent
;
241 image
->format
= pCreateInfo
->format
;
242 image
->levels
= pCreateInfo
->mipLevels
;
243 image
->array_size
= pCreateInfo
->arraySize
;
244 image
->surf_type
= surf_type
;
246 if (likely(!format_info
->has_stencil
|| format_info
->depth_format
)) {
247 /* The image's primary surface is a color or depth surface. */
248 r
= anv_image_make_surface(create_info
, &image
->size
, &image
->alignment
,
249 &image
->primary_surface
);
254 if (format_info
->has_stencil
) {
255 /* From the GPU's perspective, the depth buffer and stencil buffer are
256 * separate buffers. From Vulkan's perspective, though, depth and
257 * stencil reside in the same image. To satisfy Vulkan and the GPU, we
258 * place the depth and stencil buffers in the same bo.
260 VkImageCreateInfo stencil_info
= *pCreateInfo
;
261 stencil_info
.format
= VK_FORMAT_S8_UINT
;
263 r
= anv_image_make_surface(
264 &(struct anv_image_create_info
) {
265 .vk_info
= &stencil_info
,
267 &image
->size
, &image
->alignment
, &image
->stencil_surface
);
273 *pImage
= (VkImage
) image
;
279 anv_device_free(device
, image
);
285 anv_CreateImage(VkDevice device
,
286 const VkImageCreateInfo
*pCreateInfo
,
289 return anv_image_create(device
,
290 &(struct anv_image_create_info
) {
291 .vk_info
= pCreateInfo
,
297 anv_GetImageSubresourceInfo(VkDevice device
,
299 const VkImageSubresource
*pSubresource
,
300 VkSubresourceInfoType infoType
,
304 stub_return(VK_UNSUPPORTED
);
308 anv_surface_view_destroy(struct anv_device
*device
,
309 struct anv_object
*obj
, VkObjectType obj_type
)
311 struct anv_surface_view
*view
= (struct anv_surface_view
*)obj
;
313 assert(obj_type
== VK_OBJECT_TYPE_BUFFER_VIEW
||
314 obj_type
== VK_OBJECT_TYPE_IMAGE_VIEW
||
315 obj_type
== VK_OBJECT_TYPE_COLOR_ATTACHMENT_VIEW
);
317 anv_state_pool_free(&device
->surface_state_pool
, view
->surface_state
);
319 anv_device_free(device
, view
);
323 anv_image_view_init(struct anv_surface_view
*view
,
324 struct anv_device
*device
,
325 const VkImageViewCreateInfo
* pCreateInfo
,
326 struct anv_cmd_buffer
*cmd_buffer
)
328 const VkImageSubresourceRange
*range
= &pCreateInfo
->subresourceRange
;
329 struct anv_image
*image
= (struct anv_image
*) pCreateInfo
->image
;
330 struct anv_surface
*surface
;
332 const struct anv_format
*format_info
=
333 anv_format_for_vk_format(pCreateInfo
->format
);
335 if (pCreateInfo
->viewType
!= VK_IMAGE_VIEW_TYPE_2D
)
336 anv_finishme("non-2D image views");
338 switch (pCreateInfo
->subresourceRange
.aspect
) {
339 case VK_IMAGE_ASPECT_STENCIL
:
340 anv_finishme("stencil image views");
343 case VK_IMAGE_ASPECT_DEPTH
:
344 case VK_IMAGE_ASPECT_COLOR
:
345 view
->offset
= image
->offset
;
346 surface
= &image
->primary_surface
;
353 view
->bo
= image
->bo
;
354 view
->offset
= image
->offset
+ surface
->offset
;
355 view
->format
= pCreateInfo
->format
;
357 view
->extent
= (VkExtent3D
) {
358 .width
= anv_minify(image
->extent
.width
, range
->baseMipLevel
),
359 .height
= anv_minify(image
->extent
.height
, range
->baseMipLevel
),
360 .depth
= anv_minify(image
->extent
.depth
, range
->baseMipLevel
),
364 if (range
->arraySize
> 1) {
365 depth
= range
->arraySize
;
366 } else if (image
->extent
.depth
> 1) {
367 depth
= image
->extent
.depth
;
370 static const uint32_t vk_to_gen_swizzle
[] = {
371 [VK_CHANNEL_SWIZZLE_ZERO
] = SCS_ZERO
,
372 [VK_CHANNEL_SWIZZLE_ONE
] = SCS_ONE
,
373 [VK_CHANNEL_SWIZZLE_R
] = SCS_RED
,
374 [VK_CHANNEL_SWIZZLE_G
] = SCS_GREEN
,
375 [VK_CHANNEL_SWIZZLE_B
] = SCS_BLUE
,
376 [VK_CHANNEL_SWIZZLE_A
] = SCS_ALPHA
379 struct GEN8_RENDER_SURFACE_STATE surface_state
= {
380 .SurfaceType
= anv_surf_type_from_image_view_type
[pCreateInfo
->viewType
],
381 .SurfaceArray
= image
->array_size
> 1,
382 .SurfaceFormat
= format_info
->surface_format
,
383 .SurfaceVerticalAlignment
= anv_valign
[surface
->v_align
],
384 .SurfaceHorizontalAlignment
= anv_halign
[surface
->h_align
],
385 .TileMode
= surface
->tile_mode
,
386 .VerticalLineStride
= 0,
387 .VerticalLineStrideOffset
= 0,
388 .SamplerL2BypassModeDisable
= true,
389 .RenderCacheReadWriteMode
= WriteOnlyCache
,
390 .MemoryObjectControlState
= GEN8_MOCS
,
391 .BaseMipLevel
= (float) pCreateInfo
->minLod
,
392 .SurfaceQPitch
= surface
->qpitch
>> 2,
393 .Height
= image
->extent
.height
- 1,
394 .Width
= image
->extent
.width
- 1,
396 .SurfacePitch
= surface
->stride
- 1,
397 .MinimumArrayElement
= range
->baseArraySlice
,
398 .NumberofMultisamples
= MULTISAMPLECOUNT_1
,
402 /* For sampler surfaces, the hardware interprets field MIPCount/LOD as
403 * MIPCount. The range of levels accessible by the sampler engine is
404 * [SurfaceMinLOD, SurfaceMinLOD + MIPCountLOD].
406 .MIPCountLOD
= range
->mipLevels
- 1,
407 .SurfaceMinLOD
= range
->baseMipLevel
,
409 .AuxiliarySurfaceMode
= AUX_NONE
,
411 .GreenClearColor
= 0,
413 .AlphaClearColor
= 0,
414 .ShaderChannelSelectRed
= vk_to_gen_swizzle
[pCreateInfo
->channels
.r
],
415 .ShaderChannelSelectGreen
= vk_to_gen_swizzle
[pCreateInfo
->channels
.g
],
416 .ShaderChannelSelectBlue
= vk_to_gen_swizzle
[pCreateInfo
->channels
.b
],
417 .ShaderChannelSelectAlpha
= vk_to_gen_swizzle
[pCreateInfo
->channels
.a
],
418 .ResourceMinLOD
= 0.0,
419 .SurfaceBaseAddress
= { NULL
, view
->offset
},
423 view
->surface_state
=
424 anv_state_stream_alloc(&cmd_buffer
->surface_state_stream
, 64, 64);
426 view
->surface_state
=
427 anv_state_pool_alloc(&device
->surface_state_pool
, 64, 64);
429 GEN8_RENDER_SURFACE_STATE_pack(NULL
, view
->surface_state
.map
, &surface_state
);
433 anv_validate_CreateImageView(VkDevice _device
,
434 const VkImageViewCreateInfo
*pCreateInfo
,
437 const struct anv_image
*image
;
438 const VkImageSubresourceRange
*range
;
441 assert(pCreateInfo
->sType
== VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO
);
444 image
= (struct anv_image
*) pCreateInfo
->image
;
445 range
= &pCreateInfo
->subresourceRange
;
447 assert(range
->mipLevels
> 0);
448 assert(range
->arraySize
> 0);
449 assert(range
->baseMipLevel
+ range
->mipLevels
<= image
->levels
);
450 assert(range
->baseArraySlice
+ range
->arraySize
<= image
->array_size
);
452 return anv_CreateImageView(_device
, pCreateInfo
, pView
);
456 anv_CreateImageView(VkDevice _device
,
457 const VkImageViewCreateInfo
*pCreateInfo
,
460 struct anv_device
*device
= (struct anv_device
*) _device
;
461 struct anv_surface_view
*view
;
463 view
= anv_device_alloc(device
, sizeof(*view
), 8,
464 VK_SYSTEM_ALLOC_TYPE_API_OBJECT
);
466 return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY
);
468 anv_image_view_init(view
, device
, pCreateInfo
, NULL
);
470 view
->base
.destructor
= anv_surface_view_destroy
;
472 *pView
= (VkImageView
) view
;
478 anv_color_attachment_view_init(struct anv_surface_view
*view
,
479 struct anv_device
*device
,
480 const VkColorAttachmentViewCreateInfo
* pCreateInfo
,
481 struct anv_cmd_buffer
*cmd_buffer
)
483 struct anv_image
*image
= (struct anv_image
*) pCreateInfo
->image
;
484 struct anv_surface
*surface
= &image
->primary_surface
;
485 const struct anv_format
*format_info
=
486 anv_format_for_vk_format(pCreateInfo
->format
);
488 anv_assert(pCreateInfo
->arraySize
> 0);
489 anv_assert(pCreateInfo
->mipLevel
< image
->levels
);
490 anv_assert(pCreateInfo
->baseArraySlice
+ pCreateInfo
->arraySize
<= image
->array_size
);
492 if (pCreateInfo
->msaaResolveImage
)
493 anv_finishme("msaaResolveImage");
495 view
->bo
= image
->bo
;
496 view
->offset
= image
->offset
+ surface
->offset
;
497 view
->format
= pCreateInfo
->format
;
499 view
->extent
= (VkExtent3D
) {
500 .width
= anv_minify(image
->extent
.width
, pCreateInfo
->mipLevel
),
501 .height
= anv_minify(image
->extent
.height
, pCreateInfo
->mipLevel
),
502 .depth
= anv_minify(image
->extent
.depth
, pCreateInfo
->mipLevel
),
506 if (pCreateInfo
->arraySize
> 1) {
507 depth
= pCreateInfo
->arraySize
;
508 } else if (image
->extent
.depth
> 1) {
509 depth
= image
->extent
.depth
;
513 view
->surface_state
=
514 anv_state_stream_alloc(&cmd_buffer
->surface_state_stream
, 64, 64);
516 view
->surface_state
=
517 anv_state_pool_alloc(&device
->surface_state_pool
, 64, 64);
519 struct GEN8_RENDER_SURFACE_STATE surface_state
= {
520 .SurfaceType
= SURFTYPE_2D
,
521 .SurfaceArray
= image
->array_size
> 1,
522 .SurfaceFormat
= format_info
->surface_format
,
523 .SurfaceVerticalAlignment
= anv_valign
[surface
->v_align
],
524 .SurfaceHorizontalAlignment
= anv_halign
[surface
->h_align
],
525 .TileMode
= surface
->tile_mode
,
526 .VerticalLineStride
= 0,
527 .VerticalLineStrideOffset
= 0,
528 .SamplerL2BypassModeDisable
= true,
529 .RenderCacheReadWriteMode
= WriteOnlyCache
,
530 .MemoryObjectControlState
= GEN8_MOCS
,
532 .SurfaceQPitch
= surface
->qpitch
>> 2,
533 .Height
= image
->extent
.height
- 1,
534 .Width
= image
->extent
.width
- 1,
536 .SurfacePitch
= surface
->stride
- 1,
537 .MinimumArrayElement
= pCreateInfo
->baseArraySlice
,
538 .NumberofMultisamples
= MULTISAMPLECOUNT_1
,
542 /* For render target surfaces, the hardware interprets field MIPCount/LOD as
543 * LOD. The Broadwell PRM says:
545 * MIPCountLOD defines the LOD that will be rendered into.
546 * SurfaceMinLOD is ignored.
549 .MIPCountLOD
= pCreateInfo
->mipLevel
,
551 .AuxiliarySurfaceMode
= AUX_NONE
,
553 .GreenClearColor
= 0,
555 .AlphaClearColor
= 0,
556 .ShaderChannelSelectRed
= SCS_RED
,
557 .ShaderChannelSelectGreen
= SCS_GREEN
,
558 .ShaderChannelSelectBlue
= SCS_BLUE
,
559 .ShaderChannelSelectAlpha
= SCS_ALPHA
,
560 .ResourceMinLOD
= 0.0,
561 .SurfaceBaseAddress
= { NULL
, view
->offset
},
564 GEN8_RENDER_SURFACE_STATE_pack(NULL
, view
->surface_state
.map
, &surface_state
);
568 anv_CreateColorAttachmentView(VkDevice _device
,
569 const VkColorAttachmentViewCreateInfo
*pCreateInfo
,
570 VkColorAttachmentView
*pView
)
572 struct anv_device
*device
= (struct anv_device
*) _device
;
573 struct anv_surface_view
*view
;
575 assert(pCreateInfo
->sType
== VK_STRUCTURE_TYPE_COLOR_ATTACHMENT_VIEW_CREATE_INFO
);
577 view
= anv_device_alloc(device
, sizeof(*view
), 8,
578 VK_SYSTEM_ALLOC_TYPE_API_OBJECT
);
580 return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY
);
582 anv_color_attachment_view_init(view
, device
, pCreateInfo
, NULL
);
584 view
->base
.destructor
= anv_surface_view_destroy
;
586 *pView
= (VkColorAttachmentView
) view
;
592 anv_CreateDepthStencilView(VkDevice _device
,
593 const VkDepthStencilViewCreateInfo
*pCreateInfo
,
594 VkDepthStencilView
*pView
)
596 struct anv_device
*device
= (struct anv_device
*) _device
;
597 struct anv_depth_stencil_view
*view
;
598 struct anv_image
*image
= (struct anv_image
*) pCreateInfo
->image
;
599 struct anv_surface
*depth_surface
= &image
->primary_surface
;
600 struct anv_surface
*stencil_surface
= &image
->stencil_surface
;
601 const struct anv_format
*format
=
602 anv_format_for_vk_format(image
->format
);
604 assert(pCreateInfo
->sType
== VK_STRUCTURE_TYPE_DEPTH_STENCIL_VIEW_CREATE_INFO
);
606 view
= anv_device_alloc(device
, sizeof(*view
), 8,
607 VK_SYSTEM_ALLOC_TYPE_API_OBJECT
);
609 return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY
);
611 /* XXX: We don't handle any of these */
612 anv_assert(pCreateInfo
->mipLevel
== 0);
613 anv_assert(pCreateInfo
->baseArraySlice
== 0);
614 anv_assert(pCreateInfo
->arraySize
== 1);
615 anv_assert(pCreateInfo
->msaaResolveImage
== 0);
617 view
->bo
= image
->bo
;
619 view
->depth_stride
= depth_surface
->stride
;
620 view
->depth_offset
= image
->offset
+ depth_surface
->offset
;
621 view
->depth_format
= format
->depth_format
;
622 view
->depth_qpitch
= 0; /* FINISHME: QPitch */
624 view
->stencil_stride
= stencil_surface
->stride
;
625 view
->stencil_offset
= image
->offset
+ stencil_surface
->offset
;
626 view
->stencil_qpitch
= 0; /* FINISHME: QPitch */
628 *pView
= (VkDepthStencilView
) view
;