2 * Copyright © 2016 Red Hat.
3 * Copyright © 2016 Bas Nieuwenhuizen
5 * based in part on anv driver which is:
6 * Copyright © 2015 Intel Corporation
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice (including the next
16 * paragraph) shall be included in all copies or substantial portions of the
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 * DEALINGS IN THE SOFTWARE.
28 #include "tu_private.h"
30 #include "util/debug.h"
31 #include "util/u_atomic.h"
32 #include "vk_format.h"
36 image_level_linear(struct tu_image
*image
, int level
)
38 unsigned w
= u_minify(image
->extent
.width
, level
);
47 } tile_alignment
[] = {
48 [1] = { 128, 32 }, [2] = { 128, 16 }, [3] = { 128, 16 }, [4] = { 64, 16 },
49 [8] = { 64, 16 }, [12] = { 64, 16 }, [16] = { 64, 16 },
53 setup_slices(struct tu_image
*image
, const VkImageCreateInfo
*pCreateInfo
)
55 enum vk_format_layout layout
=
56 vk_format_description(pCreateInfo
->format
)->layout
;
57 uint32_t layer_size
= 0;
58 uint32_t width
= pCreateInfo
->extent
.width
;
59 uint32_t height
= pCreateInfo
->extent
.height
;
60 uint32_t depth
= pCreateInfo
->extent
.depth
;
61 bool layer_first
= pCreateInfo
->imageType
!= VK_IMAGE_TYPE_3D
;
62 uint32_t alignment
= pCreateInfo
->imageType
== VK_IMAGE_TYPE_3D
? 4096 : 1;
63 uint32_t cpp
= vk_format_get_blocksize(pCreateInfo
->format
);
65 uint32_t heightalign
= tile_alignment
[cpp
].heightalign
;
67 for (unsigned level
= 0; level
< pCreateInfo
->mipLevels
; level
++) {
68 struct tu_image_level
*slice
= &image
->levels
[level
];
69 bool linear_level
= image_level_linear(image
, level
);
70 uint32_t aligned_height
= height
;
74 if (image
->tile_mode
&& !linear_level
) {
75 pitchalign
= tile_alignment
[cpp
].pitchalign
;
76 aligned_height
= align(aligned_height
, heightalign
);
80 /* The blits used for mem<->gmem work at a granularity of
81 * 32x32, which can cause faults due to over-fetch on the
82 * last level. The simple solution is to over-allocate a
83 * bit the last level to ensure any over-fetch is harmless.
84 * The pitch is already sufficiently aligned, but height
87 if ((level
+ 1 == pCreateInfo
->mipLevels
))
88 aligned_height
= align(aligned_height
, 32);
91 if (layout
== VK_FORMAT_LAYOUT_ASTC
)
92 slice
->pitch
= util_align_npot(
94 pitchalign
* vk_format_get_blockwidth(pCreateInfo
->format
));
96 slice
->pitch
= align(width
, pitchalign
);
98 slice
->offset
= layer_size
;
99 blocks
= vk_format_get_block_count(pCreateInfo
->format
, slice
->pitch
,
102 /* 1d array and 2d array textures must all have the same layer size
103 * for each miplevel on a3xx. 3d textures can have different layer
104 * sizes for high levels, but the hw auto-sizer is buggy (or at least
105 * different than what this code does), so as soon as the layer size
106 * range gets into range, we stop reducing it.
108 if (pCreateInfo
->imageType
== VK_IMAGE_TYPE_3D
&&
110 (level
> 1 && image
->levels
[level
- 1].size
> 0xf000)))
111 slice
->size
= align(blocks
* cpp
, alignment
);
112 else if (level
== 0 || layer_first
|| alignment
== 1)
113 slice
->size
= align(blocks
* cpp
, alignment
);
115 slice
->size
= image
->levels
[level
- 1].size
;
117 layer_size
+= slice
->size
* depth
;
119 width
= u_minify(width
, 1);
120 height
= u_minify(height
, 1);
121 depth
= u_minify(depth
, 1);
124 image
->layer_size
= align(layer_size
, 4096);
128 tu_image_create(VkDevice _device
,
129 const struct tu_image_create_info
*create_info
,
130 const VkAllocationCallbacks
*alloc
,
133 TU_FROM_HANDLE(tu_device
, device
, _device
);
134 const VkImageCreateInfo
*pCreateInfo
= create_info
->vk_info
;
135 struct tu_image
*image
= NULL
;
136 assert(pCreateInfo
->sType
== VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO
);
138 tu_assert(pCreateInfo
->mipLevels
> 0);
139 tu_assert(pCreateInfo
->arrayLayers
> 0);
140 tu_assert(pCreateInfo
->samples
> 0);
141 tu_assert(pCreateInfo
->extent
.width
> 0);
142 tu_assert(pCreateInfo
->extent
.height
> 0);
143 tu_assert(pCreateInfo
->extent
.depth
> 0);
145 image
= vk_zalloc2(&device
->alloc
, alloc
, sizeof(*image
), 8,
146 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
148 return vk_error(device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
150 image
->type
= pCreateInfo
->imageType
;
152 image
->vk_format
= pCreateInfo
->format
;
153 image
->tiling
= pCreateInfo
->tiling
;
154 image
->usage
= pCreateInfo
->usage
;
155 image
->flags
= pCreateInfo
->flags
;
156 image
->extent
= pCreateInfo
->extent
;
157 image
->level_count
= pCreateInfo
->mipLevels
;
158 image
->layer_count
= pCreateInfo
->arrayLayers
;
160 image
->exclusive
= pCreateInfo
->sharingMode
== VK_SHARING_MODE_EXCLUSIVE
;
161 if (pCreateInfo
->sharingMode
== VK_SHARING_MODE_CONCURRENT
) {
162 for (uint32_t i
= 0; i
< pCreateInfo
->queueFamilyIndexCount
; ++i
)
163 if (pCreateInfo
->pQueueFamilyIndices
[i
] ==
164 VK_QUEUE_FAMILY_EXTERNAL
)
165 image
->queue_family_mask
|= (1u << TU_MAX_QUEUE_FAMILIES
) - 1u;
167 image
->queue_family_mask
|=
168 1u << pCreateInfo
->pQueueFamilyIndices
[i
];
172 vk_find_struct_const(pCreateInfo
->pNext
,
173 EXTERNAL_MEMORY_IMAGE_CREATE_INFO
) != NULL
;
175 image
->tile_mode
= TILE6_LINEAR
;
176 if (pCreateInfo
->tiling
== VK_IMAGE_TILING_OPTIMAL
&& !create_info
->scanout
)
177 image
->tile_mode
= TILE6_3
;
179 setup_slices(image
, pCreateInfo
);
181 image
->size
= image
->layer_size
* pCreateInfo
->arrayLayers
;
182 *pImage
= tu_image_to_handle(image
);
187 static enum a6xx_tex_fetchsize
188 tu6_fetchsize(VkFormat format
)
190 if (vk_format_description(format
)->layout
== VK_FORMAT_LAYOUT_ASTC
)
191 return TFETCH6_16_BYTE
;
193 switch (vk_format_get_blocksize(format
) / vk_format_get_blockwidth(format
)) {
194 case 1: return TFETCH6_1_BYTE
;
195 case 2: return TFETCH6_2_BYTE
;
196 case 4: return TFETCH6_4_BYTE
;
197 case 8: return TFETCH6_8_BYTE
;
198 case 16: return TFETCH6_16_BYTE
;
200 unreachable("bad block size");
205 tu6_texswiz(const VkComponentMapping
*comps
, const unsigned char *fmt_swiz
)
207 unsigned char swiz
[4] = {comps
->r
, comps
->g
, comps
->b
, comps
->a
};
208 unsigned char vk_swizzle
[] = {
209 [VK_COMPONENT_SWIZZLE_ZERO
] = A6XX_TEX_ZERO
,
210 [VK_COMPONENT_SWIZZLE_ONE
] = A6XX_TEX_ONE
,
211 [VK_COMPONENT_SWIZZLE_R
] = A6XX_TEX_X
,
212 [VK_COMPONENT_SWIZZLE_G
] = A6XX_TEX_Y
,
213 [VK_COMPONENT_SWIZZLE_B
] = A6XX_TEX_Z
,
214 [VK_COMPONENT_SWIZZLE_A
] = A6XX_TEX_W
,
216 for (unsigned i
= 0; i
< 4; i
++) {
217 swiz
[i
] = (swiz
[i
] == VK_COMPONENT_SWIZZLE_IDENTITY
) ? i
: vk_swizzle
[swiz
[i
]];
218 /* if format has 0/1 in channel, use that (needed for bc1_rgb) */
220 switch (fmt_swiz
[swiz
[i
]]) {
221 case VK_SWIZZLE_0
: swiz
[i
] = A6XX_TEX_ZERO
; break;
222 case VK_SWIZZLE_1
: swiz
[i
] = A6XX_TEX_ONE
; break;
227 return A6XX_TEX_CONST_0_SWIZ_X(swiz
[0]) |
228 A6XX_TEX_CONST_0_SWIZ_Y(swiz
[1]) |
229 A6XX_TEX_CONST_0_SWIZ_Z(swiz
[2]) |
230 A6XX_TEX_CONST_0_SWIZ_W(swiz
[3]);
233 static enum a6xx_tex_type
234 tu6_tex_type(VkImageViewType type
)
238 case VK_IMAGE_VIEW_TYPE_1D
:
239 case VK_IMAGE_VIEW_TYPE_1D_ARRAY
:
241 case VK_IMAGE_VIEW_TYPE_2D
:
242 case VK_IMAGE_VIEW_TYPE_2D_ARRAY
:
244 case VK_IMAGE_VIEW_TYPE_3D
:
246 case VK_IMAGE_VIEW_TYPE_CUBE
:
247 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY
:
248 return A6XX_TEX_CUBE
;
253 tu_image_view_init(struct tu_image_view
*iview
,
254 struct tu_device
*device
,
255 const VkImageViewCreateInfo
*pCreateInfo
)
257 TU_FROM_HANDLE(tu_image
, image
, pCreateInfo
->image
);
258 const VkImageSubresourceRange
*range
= &pCreateInfo
->subresourceRange
;
260 switch (image
->type
) {
261 case VK_IMAGE_TYPE_1D
:
262 case VK_IMAGE_TYPE_2D
:
263 assert(range
->baseArrayLayer
+ tu_get_layerCount(image
, range
) <=
266 case VK_IMAGE_TYPE_3D
:
267 assert(range
->baseArrayLayer
+ tu_get_layerCount(image
, range
) <=
268 tu_minify(image
->extent
.depth
, range
->baseMipLevel
));
271 unreachable("bad VkImageType");
274 iview
->image
= image
;
275 iview
->type
= pCreateInfo
->viewType
;
276 iview
->vk_format
= pCreateInfo
->format
;
277 iview
->aspect_mask
= pCreateInfo
->subresourceRange
.aspectMask
;
279 if (iview
->aspect_mask
== VK_IMAGE_ASPECT_STENCIL_BIT
) {
280 iview
->vk_format
= vk_format_stencil_only(iview
->vk_format
);
281 } else if (iview
->aspect_mask
== VK_IMAGE_ASPECT_DEPTH_BIT
) {
282 iview
->vk_format
= vk_format_depth_only(iview
->vk_format
);
286 iview
->extent
= image
->extent
;
288 iview
->base_layer
= range
->baseArrayLayer
;
289 iview
->layer_count
= tu_get_layerCount(image
, range
);
290 iview
->base_mip
= range
->baseMipLevel
;
291 iview
->level_count
= tu_get_levelCount(image
, range
);
293 memset(iview
->descriptor
, 0, sizeof(iview
->descriptor
));
295 const struct tu_native_format
*fmt
= tu6_get_native_format(iview
->vk_format
);
296 struct tu_image_level
*slice0
= &image
->levels
[iview
->base_mip
];
297 uint64_t base_addr
= image
->bo
->iova
+ iview
->base_layer
* image
->layer_size
+ slice0
->offset
;
298 uint32_t pitch
= (slice0
->pitch
/ vk_format_get_blockwidth(iview
->vk_format
)) *
299 vk_format_get_blocksize(iview
->vk_format
);
300 enum a6xx_tile_mode tile_mode
=
301 image_level_linear(image
, iview
->base_mip
) ? TILE6_LINEAR
: image
->tile_mode
;
303 iview
->descriptor
[0] =
304 A6XX_TEX_CONST_0_TILE_MODE(tile_mode
) |
305 COND(vk_format_is_srgb(iview
->vk_format
), A6XX_TEX_CONST_0_SRGB
) |
306 A6XX_TEX_CONST_0_FMT(fmt
->tex
) |
307 A6XX_TEX_CONST_0_SAMPLES(0) |
308 A6XX_TEX_CONST_0_SWAP(image
->tile_mode
? WZYX
: fmt
->swap
) |
309 tu6_texswiz(&pCreateInfo
->components
, vk_format_description(iview
->vk_format
)->swizzle
) |
310 A6XX_TEX_CONST_0_MIPLVLS(iview
->level_count
- 1);
311 iview
->descriptor
[1] =
312 A6XX_TEX_CONST_1_WIDTH(u_minify(image
->extent
.width
, iview
->base_mip
)) |
313 A6XX_TEX_CONST_1_HEIGHT(u_minify(image
->extent
.height
, iview
->base_mip
));
314 iview
->descriptor
[2] =
315 A6XX_TEX_CONST_2_FETCHSIZE(tu6_fetchsize(iview
->vk_format
)) |
316 A6XX_TEX_CONST_2_PITCH(pitch
) |
317 A6XX_TEX_CONST_2_TYPE(tu6_tex_type(pCreateInfo
->viewType
));
318 iview
->descriptor
[3] = 0;
319 iview
->descriptor
[4] = base_addr
;
320 iview
->descriptor
[5] = base_addr
>> 32;
322 if (pCreateInfo
->viewType
!= VK_IMAGE_VIEW_TYPE_3D
) {
323 iview
->descriptor
[3] |= A6XX_TEX_CONST_3_ARRAY_PITCH(image
->layer_size
);
324 iview
->descriptor
[5] |= A6XX_TEX_CONST_5_DEPTH(iview
->layer_count
);
326 iview
->descriptor
[3] |=
327 A6XX_TEX_CONST_3_MIN_LAYERSZ(image
->levels
[image
->level_count
- 1].size
) |
328 A6XX_TEX_CONST_3_ARRAY_PITCH(slice0
->size
);
329 iview
->descriptor
[5] |=
330 A6XX_TEX_CONST_5_DEPTH(u_minify(image
->extent
.depth
, iview
->base_mip
));
335 tu_image_queue_family_mask(const struct tu_image
*image
,
337 uint32_t queue_family
)
339 if (!image
->exclusive
)
340 return image
->queue_family_mask
;
341 if (family
== VK_QUEUE_FAMILY_EXTERNAL
)
342 return (1u << TU_MAX_QUEUE_FAMILIES
) - 1u;
343 if (family
== VK_QUEUE_FAMILY_IGNORED
)
344 return 1u << queue_family
;
349 tu_CreateImage(VkDevice device
,
350 const VkImageCreateInfo
*pCreateInfo
,
351 const VkAllocationCallbacks
*pAllocator
,
355 const VkNativeBufferANDROID
*gralloc_info
=
356 vk_find_struct_const(pCreateInfo
->pNext
, NATIVE_BUFFER_ANDROID
);
359 return tu_image_from_gralloc(device
, pCreateInfo
, gralloc_info
,
363 const struct wsi_image_create_info
*wsi_info
=
364 vk_find_struct_const(pCreateInfo
->pNext
, WSI_IMAGE_CREATE_INFO_MESA
);
365 bool scanout
= wsi_info
&& wsi_info
->scanout
;
367 return tu_image_create(device
,
368 &(struct tu_image_create_info
) {
369 .vk_info
= pCreateInfo
,
376 tu_DestroyImage(VkDevice _device
,
378 const VkAllocationCallbacks
*pAllocator
)
380 TU_FROM_HANDLE(tu_device
, device
, _device
);
381 TU_FROM_HANDLE(tu_image
, image
, _image
);
386 if (image
->owned_memory
!= VK_NULL_HANDLE
)
387 tu_FreeMemory(_device
, image
->owned_memory
, pAllocator
);
389 vk_free2(&device
->alloc
, pAllocator
, image
);
393 tu_GetImageSubresourceLayout(VkDevice _device
,
395 const VkImageSubresource
*pSubresource
,
396 VkSubresourceLayout
*pLayout
)
398 TU_FROM_HANDLE(tu_image
, image
, _image
);
400 const uint32_t layer_offset
= image
->layer_size
* pSubresource
->arrayLayer
;
401 const struct tu_image_level
*level
=
402 image
->levels
+ pSubresource
->mipLevel
;
404 pLayout
->offset
= layer_offset
+ level
->offset
;
405 pLayout
->size
= level
->size
;
407 level
->pitch
* vk_format_get_blocksize(image
->vk_format
);
408 pLayout
->arrayPitch
= image
->layer_size
;
409 pLayout
->depthPitch
= level
->size
;
413 tu_CreateImageView(VkDevice _device
,
414 const VkImageViewCreateInfo
*pCreateInfo
,
415 const VkAllocationCallbacks
*pAllocator
,
418 TU_FROM_HANDLE(tu_device
, device
, _device
);
419 struct tu_image_view
*view
;
421 view
= vk_alloc2(&device
->alloc
, pAllocator
, sizeof(*view
), 8,
422 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
424 return vk_error(device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
426 tu_image_view_init(view
, device
, pCreateInfo
);
428 *pView
= tu_image_view_to_handle(view
);
434 tu_DestroyImageView(VkDevice _device
,
436 const VkAllocationCallbacks
*pAllocator
)
438 TU_FROM_HANDLE(tu_device
, device
, _device
);
439 TU_FROM_HANDLE(tu_image_view
, iview
, _iview
);
443 vk_free2(&device
->alloc
, pAllocator
, iview
);
447 tu_buffer_view_init(struct tu_buffer_view
*view
,
448 struct tu_device
*device
,
449 const VkBufferViewCreateInfo
*pCreateInfo
)
451 TU_FROM_HANDLE(tu_buffer
, buffer
, pCreateInfo
->buffer
);
453 view
->range
= pCreateInfo
->range
== VK_WHOLE_SIZE
454 ? buffer
->size
- pCreateInfo
->offset
455 : pCreateInfo
->range
;
456 view
->vk_format
= pCreateInfo
->format
;
460 tu_CreateBufferView(VkDevice _device
,
461 const VkBufferViewCreateInfo
*pCreateInfo
,
462 const VkAllocationCallbacks
*pAllocator
,
465 TU_FROM_HANDLE(tu_device
, device
, _device
);
466 struct tu_buffer_view
*view
;
468 view
= vk_alloc2(&device
->alloc
, pAllocator
, sizeof(*view
), 8,
469 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
471 return vk_error(device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
473 tu_buffer_view_init(view
, device
, pCreateInfo
);
475 *pView
= tu_buffer_view_to_handle(view
);
481 tu_DestroyBufferView(VkDevice _device
,
482 VkBufferView bufferView
,
483 const VkAllocationCallbacks
*pAllocator
)
485 TU_FROM_HANDLE(tu_device
, device
, _device
);
486 TU_FROM_HANDLE(tu_buffer_view
, view
, bufferView
);
491 vk_free2(&device
->alloc
, pAllocator
, view
);