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
);
43 tu6_get_image_tile_mode(struct tu_image
*image
, int level
)
45 if (image_level_linear(image
, level
))
48 return image
->tile_mode
;
51 /* indexed by cpp, including msaa 2x and 4x: */
55 } tile_alignment
[] = {
69 /* special case for r8g8: */
74 setup_slices(struct tu_image
*image
, const VkImageCreateInfo
*pCreateInfo
)
76 VkFormat format
= pCreateInfo
->format
;
77 enum vk_format_layout layout
= vk_format_description(format
)->layout
;
78 uint32_t layer_size
= 0;
81 /* The r8g8 format seems to not play by the normal tiling rules: */
82 if (image
->cpp
== 2 && vk_format_get_nr_components(format
) == 2)
85 for (unsigned level
= 0; level
< pCreateInfo
->mipLevels
; level
++) {
86 struct tu_image_level
*slice
= &image
->levels
[level
];
87 uint32_t width
= u_minify(pCreateInfo
->extent
.width
, level
);
88 uint32_t height
= u_minify(pCreateInfo
->extent
.height
, level
);
89 uint32_t depth
= u_minify(pCreateInfo
->extent
.depth
, level
);
90 uint32_t aligned_height
= height
;
94 if (image
->tile_mode
&& !image_level_linear(image
, level
)) {
95 /* tiled levels of 3D textures are rounded up to PoT dimensions: */
96 if (pCreateInfo
->imageType
== VK_IMAGE_TYPE_3D
) {
97 width
= util_next_power_of_two(width
);
98 height
= aligned_height
= util_next_power_of_two(height
);
100 pitchalign
= tile_alignment
[ta
].pitchalign
;
101 aligned_height
= align(aligned_height
, tile_alignment
[ta
].heightalign
);
106 /* The blits used for mem<->gmem work at a granularity of
107 * 32x32, which can cause faults due to over-fetch on the
108 * last level. The simple solution is to over-allocate a
109 * bit the last level to ensure any over-fetch is harmless.
110 * The pitch is already sufficiently aligned, but height
113 if (level
+ 1 == pCreateInfo
->mipLevels
)
114 aligned_height
= align(aligned_height
, 32);
116 if (layout
== VK_FORMAT_LAYOUT_ASTC
)
118 util_align_npot(width
, pitchalign
* vk_format_get_blockwidth(format
));
120 slice
->pitch
= align(width
, pitchalign
);
122 slice
->offset
= layer_size
;
123 blocks
= vk_format_get_block_count(format
, slice
->pitch
, aligned_height
);
125 /* 1d array and 2d array textures must all have the same layer size
126 * for each miplevel on a6xx. 3d textures can have different layer
127 * sizes for high levels, but the hw auto-sizer is buggy (or at least
128 * different than what this code does), so as soon as the layer size
129 * range gets into range, we stop reducing it.
131 if (pCreateInfo
->imageType
== VK_IMAGE_TYPE_3D
) {
132 if (level
< 1 || image
->levels
[level
- 1].size
> 0xf000) {
133 slice
->size
= align(blocks
* image
->cpp
, 4096);
135 slice
->size
= image
->levels
[level
- 1].size
;
138 slice
->size
= blocks
* image
->cpp
;
141 layer_size
+= slice
->size
* depth
;
144 image
->layer_size
= align(layer_size
, 4096);
148 tu_image_create(VkDevice _device
,
149 const struct tu_image_create_info
*create_info
,
150 const VkAllocationCallbacks
*alloc
,
153 TU_FROM_HANDLE(tu_device
, device
, _device
);
154 const VkImageCreateInfo
*pCreateInfo
= create_info
->vk_info
;
155 struct tu_image
*image
= NULL
;
156 assert(pCreateInfo
->sType
== VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO
);
158 tu_assert(pCreateInfo
->mipLevels
> 0);
159 tu_assert(pCreateInfo
->arrayLayers
> 0);
160 tu_assert(pCreateInfo
->samples
> 0);
161 tu_assert(pCreateInfo
->extent
.width
> 0);
162 tu_assert(pCreateInfo
->extent
.height
> 0);
163 tu_assert(pCreateInfo
->extent
.depth
> 0);
165 image
= vk_zalloc2(&device
->alloc
, alloc
, sizeof(*image
), 8,
166 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
168 return vk_error(device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
170 image
->type
= pCreateInfo
->imageType
;
172 image
->vk_format
= pCreateInfo
->format
;
173 image
->tiling
= pCreateInfo
->tiling
;
174 image
->usage
= pCreateInfo
->usage
;
175 image
->flags
= pCreateInfo
->flags
;
176 image
->extent
= pCreateInfo
->extent
;
177 image
->level_count
= pCreateInfo
->mipLevels
;
178 image
->layer_count
= pCreateInfo
->arrayLayers
;
179 image
->samples
= pCreateInfo
->samples
;
180 image
->cpp
= vk_format_get_blocksize(image
->vk_format
) * image
->samples
;
182 image
->exclusive
= pCreateInfo
->sharingMode
== VK_SHARING_MODE_EXCLUSIVE
;
183 if (pCreateInfo
->sharingMode
== VK_SHARING_MODE_CONCURRENT
) {
184 for (uint32_t i
= 0; i
< pCreateInfo
->queueFamilyIndexCount
; ++i
)
185 if (pCreateInfo
->pQueueFamilyIndices
[i
] ==
186 VK_QUEUE_FAMILY_EXTERNAL
)
187 image
->queue_family_mask
|= (1u << TU_MAX_QUEUE_FAMILIES
) - 1u;
189 image
->queue_family_mask
|=
190 1u << pCreateInfo
->pQueueFamilyIndices
[i
];
194 vk_find_struct_const(pCreateInfo
->pNext
,
195 EXTERNAL_MEMORY_IMAGE_CREATE_INFO
) != NULL
;
197 image
->tile_mode
= TILE6_3
;
199 if (pCreateInfo
->tiling
== VK_IMAGE_TILING_LINEAR
||
200 /* compressed textures can't use tiling? */
201 vk_format_is_compressed(image
->vk_format
) ||
202 /* scanout needs to be linear (what about tiling modifiers?) */
203 create_info
->scanout
||
204 /* image_to_image copy doesn't deal with tiling+swap */
205 tu6_get_native_format(image
->vk_format
)->swap
||
206 /* r8g8 formats are tiled different and could break image_to_image copy */
207 (image
->cpp
== 2 && vk_format_get_nr_components(image
->vk_format
) == 2))
208 image
->tile_mode
= TILE6_LINEAR
;
210 setup_slices(image
, pCreateInfo
);
212 image
->size
= image
->layer_size
* pCreateInfo
->arrayLayers
;
213 *pImage
= tu_image_to_handle(image
);
218 static enum a6xx_tex_fetchsize
219 tu6_fetchsize(VkFormat format
)
221 if (vk_format_description(format
)->layout
== VK_FORMAT_LAYOUT_ASTC
)
222 return TFETCH6_16_BYTE
;
224 switch (vk_format_get_blocksize(format
) / vk_format_get_blockwidth(format
)) {
225 case 1: return TFETCH6_1_BYTE
;
226 case 2: return TFETCH6_2_BYTE
;
227 case 4: return TFETCH6_4_BYTE
;
228 case 8: return TFETCH6_8_BYTE
;
229 case 16: return TFETCH6_16_BYTE
;
231 unreachable("bad block size");
236 tu6_texswiz(const VkComponentMapping
*comps
, const unsigned char *fmt_swiz
)
238 unsigned char swiz
[4] = {comps
->r
, comps
->g
, comps
->b
, comps
->a
};
239 unsigned char vk_swizzle
[] = {
240 [VK_COMPONENT_SWIZZLE_ZERO
] = A6XX_TEX_ZERO
,
241 [VK_COMPONENT_SWIZZLE_ONE
] = A6XX_TEX_ONE
,
242 [VK_COMPONENT_SWIZZLE_R
] = A6XX_TEX_X
,
243 [VK_COMPONENT_SWIZZLE_G
] = A6XX_TEX_Y
,
244 [VK_COMPONENT_SWIZZLE_B
] = A6XX_TEX_Z
,
245 [VK_COMPONENT_SWIZZLE_A
] = A6XX_TEX_W
,
247 for (unsigned i
= 0; i
< 4; i
++) {
248 swiz
[i
] = (swiz
[i
] == VK_COMPONENT_SWIZZLE_IDENTITY
) ? i
: vk_swizzle
[swiz
[i
]];
249 /* if format has 0/1 in channel, use that (needed for bc1_rgb) */
251 switch (fmt_swiz
[swiz
[i
]]) {
252 case VK_SWIZZLE_0
: swiz
[i
] = A6XX_TEX_ZERO
; break;
253 case VK_SWIZZLE_1
: swiz
[i
] = A6XX_TEX_ONE
; break;
258 return A6XX_TEX_CONST_0_SWIZ_X(swiz
[0]) |
259 A6XX_TEX_CONST_0_SWIZ_Y(swiz
[1]) |
260 A6XX_TEX_CONST_0_SWIZ_Z(swiz
[2]) |
261 A6XX_TEX_CONST_0_SWIZ_W(swiz
[3]);
264 static enum a6xx_tex_type
265 tu6_tex_type(VkImageViewType type
)
269 case VK_IMAGE_VIEW_TYPE_1D
:
270 case VK_IMAGE_VIEW_TYPE_1D_ARRAY
:
272 case VK_IMAGE_VIEW_TYPE_2D
:
273 case VK_IMAGE_VIEW_TYPE_2D_ARRAY
:
275 case VK_IMAGE_VIEW_TYPE_3D
:
277 case VK_IMAGE_VIEW_TYPE_CUBE
:
278 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY
:
279 return A6XX_TEX_CUBE
;
284 tu_image_view_init(struct tu_image_view
*iview
,
285 struct tu_device
*device
,
286 const VkImageViewCreateInfo
*pCreateInfo
)
288 TU_FROM_HANDLE(tu_image
, image
, pCreateInfo
->image
);
289 const VkImageSubresourceRange
*range
= &pCreateInfo
->subresourceRange
;
291 switch (image
->type
) {
292 case VK_IMAGE_TYPE_1D
:
293 case VK_IMAGE_TYPE_2D
:
294 assert(range
->baseArrayLayer
+ tu_get_layerCount(image
, range
) <=
297 case VK_IMAGE_TYPE_3D
:
298 assert(range
->baseArrayLayer
+ tu_get_layerCount(image
, range
) <=
299 tu_minify(image
->extent
.depth
, range
->baseMipLevel
));
302 unreachable("bad VkImageType");
305 iview
->image
= image
;
306 iview
->type
= pCreateInfo
->viewType
;
307 iview
->vk_format
= pCreateInfo
->format
;
308 iview
->aspect_mask
= pCreateInfo
->subresourceRange
.aspectMask
;
310 if (iview
->aspect_mask
== VK_IMAGE_ASPECT_STENCIL_BIT
) {
311 iview
->vk_format
= vk_format_stencil_only(iview
->vk_format
);
312 } else if (iview
->aspect_mask
== VK_IMAGE_ASPECT_DEPTH_BIT
) {
313 iview
->vk_format
= vk_format_depth_only(iview
->vk_format
);
317 iview
->extent
= image
->extent
;
319 iview
->base_layer
= range
->baseArrayLayer
;
320 iview
->layer_count
= tu_get_layerCount(image
, range
);
321 iview
->base_mip
= range
->baseMipLevel
;
322 iview
->level_count
= tu_get_levelCount(image
, range
);
324 memset(iview
->descriptor
, 0, sizeof(iview
->descriptor
));
326 const struct tu_native_format
*fmt
= tu6_get_native_format(iview
->vk_format
);
327 struct tu_image_level
*slice0
= &image
->levels
[iview
->base_mip
];
328 uint64_t base_addr
= image
->bo
->iova
+ iview
->base_layer
* image
->layer_size
+ slice0
->offset
;
329 uint32_t pitch
= (slice0
->pitch
/ vk_format_get_blockwidth(iview
->vk_format
)) *
330 vk_format_get_blocksize(iview
->vk_format
);
331 enum a6xx_tile_mode tile_mode
=
332 image_level_linear(image
, iview
->base_mip
) ? TILE6_LINEAR
: image
->tile_mode
;
334 iview
->descriptor
[0] =
335 A6XX_TEX_CONST_0_TILE_MODE(tile_mode
) |
336 COND(vk_format_is_srgb(iview
->vk_format
), A6XX_TEX_CONST_0_SRGB
) |
337 A6XX_TEX_CONST_0_FMT(fmt
->tex
) |
338 A6XX_TEX_CONST_0_SAMPLES(0) |
339 A6XX_TEX_CONST_0_SWAP(image
->tile_mode
? WZYX
: fmt
->swap
) |
340 tu6_texswiz(&pCreateInfo
->components
, vk_format_description(iview
->vk_format
)->swizzle
) |
341 A6XX_TEX_CONST_0_MIPLVLS(iview
->level_count
- 1);
342 iview
->descriptor
[1] =
343 A6XX_TEX_CONST_1_WIDTH(u_minify(image
->extent
.width
, iview
->base_mip
)) |
344 A6XX_TEX_CONST_1_HEIGHT(u_minify(image
->extent
.height
, iview
->base_mip
));
345 iview
->descriptor
[2] =
346 A6XX_TEX_CONST_2_FETCHSIZE(tu6_fetchsize(iview
->vk_format
)) |
347 A6XX_TEX_CONST_2_PITCH(pitch
) |
348 A6XX_TEX_CONST_2_TYPE(tu6_tex_type(pCreateInfo
->viewType
));
349 iview
->descriptor
[3] = 0;
350 iview
->descriptor
[4] = base_addr
;
351 iview
->descriptor
[5] = base_addr
>> 32;
353 if (pCreateInfo
->viewType
!= VK_IMAGE_VIEW_TYPE_3D
) {
354 iview
->descriptor
[3] |= A6XX_TEX_CONST_3_ARRAY_PITCH(image
->layer_size
);
355 iview
->descriptor
[5] |= A6XX_TEX_CONST_5_DEPTH(iview
->layer_count
);
357 iview
->descriptor
[3] |=
358 A6XX_TEX_CONST_3_MIN_LAYERSZ(image
->levels
[image
->level_count
- 1].size
) |
359 A6XX_TEX_CONST_3_ARRAY_PITCH(slice0
->size
);
360 iview
->descriptor
[5] |=
361 A6XX_TEX_CONST_5_DEPTH(u_minify(image
->extent
.depth
, iview
->base_mip
));
366 tu_image_queue_family_mask(const struct tu_image
*image
,
368 uint32_t queue_family
)
370 if (!image
->exclusive
)
371 return image
->queue_family_mask
;
372 if (family
== VK_QUEUE_FAMILY_EXTERNAL
)
373 return (1u << TU_MAX_QUEUE_FAMILIES
) - 1u;
374 if (family
== VK_QUEUE_FAMILY_IGNORED
)
375 return 1u << queue_family
;
380 tu_CreateImage(VkDevice device
,
381 const VkImageCreateInfo
*pCreateInfo
,
382 const VkAllocationCallbacks
*pAllocator
,
386 const VkNativeBufferANDROID
*gralloc_info
=
387 vk_find_struct_const(pCreateInfo
->pNext
, NATIVE_BUFFER_ANDROID
);
390 return tu_image_from_gralloc(device
, pCreateInfo
, gralloc_info
,
394 const struct wsi_image_create_info
*wsi_info
=
395 vk_find_struct_const(pCreateInfo
->pNext
, WSI_IMAGE_CREATE_INFO_MESA
);
396 bool scanout
= wsi_info
&& wsi_info
->scanout
;
398 return tu_image_create(device
,
399 &(struct tu_image_create_info
) {
400 .vk_info
= pCreateInfo
,
407 tu_DestroyImage(VkDevice _device
,
409 const VkAllocationCallbacks
*pAllocator
)
411 TU_FROM_HANDLE(tu_device
, device
, _device
);
412 TU_FROM_HANDLE(tu_image
, image
, _image
);
417 if (image
->owned_memory
!= VK_NULL_HANDLE
)
418 tu_FreeMemory(_device
, image
->owned_memory
, pAllocator
);
420 vk_free2(&device
->alloc
, pAllocator
, image
);
424 tu_GetImageSubresourceLayout(VkDevice _device
,
426 const VkImageSubresource
*pSubresource
,
427 VkSubresourceLayout
*pLayout
)
429 TU_FROM_HANDLE(tu_image
, image
, _image
);
431 const uint32_t layer_offset
= image
->layer_size
* pSubresource
->arrayLayer
;
432 const struct tu_image_level
*level
=
433 image
->levels
+ pSubresource
->mipLevel
;
435 pLayout
->offset
= layer_offset
+ level
->offset
;
436 pLayout
->size
= level
->size
;
438 level
->pitch
* vk_format_get_blocksize(image
->vk_format
);
439 pLayout
->arrayPitch
= image
->layer_size
;
440 pLayout
->depthPitch
= level
->size
;
444 tu_CreateImageView(VkDevice _device
,
445 const VkImageViewCreateInfo
*pCreateInfo
,
446 const VkAllocationCallbacks
*pAllocator
,
449 TU_FROM_HANDLE(tu_device
, device
, _device
);
450 struct tu_image_view
*view
;
452 view
= vk_alloc2(&device
->alloc
, pAllocator
, sizeof(*view
), 8,
453 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
455 return vk_error(device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
457 tu_image_view_init(view
, device
, pCreateInfo
);
459 *pView
= tu_image_view_to_handle(view
);
465 tu_DestroyImageView(VkDevice _device
,
467 const VkAllocationCallbacks
*pAllocator
)
469 TU_FROM_HANDLE(tu_device
, device
, _device
);
470 TU_FROM_HANDLE(tu_image_view
, iview
, _iview
);
474 vk_free2(&device
->alloc
, pAllocator
, iview
);
478 tu_buffer_view_init(struct tu_buffer_view
*view
,
479 struct tu_device
*device
,
480 const VkBufferViewCreateInfo
*pCreateInfo
)
482 TU_FROM_HANDLE(tu_buffer
, buffer
, pCreateInfo
->buffer
);
484 view
->range
= pCreateInfo
->range
== VK_WHOLE_SIZE
485 ? buffer
->size
- pCreateInfo
->offset
486 : pCreateInfo
->range
;
487 view
->vk_format
= pCreateInfo
->format
;
491 tu_CreateBufferView(VkDevice _device
,
492 const VkBufferViewCreateInfo
*pCreateInfo
,
493 const VkAllocationCallbacks
*pAllocator
,
496 TU_FROM_HANDLE(tu_device
, device
, _device
);
497 struct tu_buffer_view
*view
;
499 view
= vk_alloc2(&device
->alloc
, pAllocator
, sizeof(*view
), 8,
500 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
502 return vk_error(device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
504 tu_buffer_view_init(view
, device
, pCreateInfo
);
506 *pView
= tu_buffer_view_to_handle(view
);
512 tu_DestroyBufferView(VkDevice _device
,
513 VkBufferView bufferView
,
514 const VkAllocationCallbacks
*pAllocator
)
516 TU_FROM_HANDLE(tu_device
, device
, _device
);
517 TU_FROM_HANDLE(tu_buffer_view
, view
, bufferView
);
522 vk_free2(&device
->alloc
, pAllocator
, view
);