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
);
42 /* indexed by cpp, including msaa 2x and 4x: */
46 } tile_alignment
[] = {
60 /* special case for r8g8: */
65 setup_slices(struct tu_image
*image
, const VkImageCreateInfo
*pCreateInfo
)
67 VkFormat format
= pCreateInfo
->format
;
68 enum vk_format_layout layout
= vk_format_description(format
)->layout
;
69 uint32_t layer_size
= 0;
72 /* The r8g8 format seems to not play by the normal tiling rules: */
73 if (image
->cpp
== 2 && vk_format_get_nr_components(format
) == 2)
76 for (unsigned level
= 0; level
< pCreateInfo
->mipLevels
; level
++) {
77 struct tu_image_level
*slice
= &image
->levels
[level
];
78 uint32_t width
= u_minify(pCreateInfo
->extent
.width
, level
);
79 uint32_t height
= u_minify(pCreateInfo
->extent
.height
, level
);
80 uint32_t depth
= u_minify(pCreateInfo
->extent
.depth
, level
);
81 uint32_t aligned_height
= height
;
85 if (image
->tile_mode
&& !image_level_linear(image
, level
)) {
86 /* tiled levels of 3D textures are rounded up to PoT dimensions: */
87 if (pCreateInfo
->imageType
== VK_IMAGE_TYPE_3D
) {
88 width
= util_next_power_of_two(width
);
89 height
= aligned_height
= util_next_power_of_two(height
);
91 pitchalign
= tile_alignment
[ta
].pitchalign
;
92 aligned_height
= align(aligned_height
, tile_alignment
[ta
].heightalign
);
97 /* The blits used for mem<->gmem work at a granularity of
98 * 32x32, which can cause faults due to over-fetch on the
99 * last level. The simple solution is to over-allocate a
100 * bit the last level to ensure any over-fetch is harmless.
101 * The pitch is already sufficiently aligned, but height
104 if (level
+ 1 == pCreateInfo
->mipLevels
)
105 aligned_height
= align(aligned_height
, 32);
107 if (layout
== VK_FORMAT_LAYOUT_ASTC
)
109 util_align_npot(width
, pitchalign
* vk_format_get_blockwidth(format
));
111 slice
->pitch
= align(width
, pitchalign
);
113 slice
->offset
= layer_size
;
114 blocks
= vk_format_get_block_count(format
, slice
->pitch
, aligned_height
);
116 /* 1d array and 2d array textures must all have the same layer size
117 * for each miplevel on a6xx. 3d textures can have different layer
118 * sizes for high levels, but the hw auto-sizer is buggy (or at least
119 * different than what this code does), so as soon as the layer size
120 * range gets into range, we stop reducing it.
122 if (pCreateInfo
->imageType
== VK_IMAGE_TYPE_3D
) {
123 if (level
< 1 || image
->levels
[level
- 1].size
> 0xf000) {
124 slice
->size
= align(blocks
* image
->cpp
, 4096);
126 slice
->size
= image
->levels
[level
- 1].size
;
129 slice
->size
= blocks
* image
->cpp
;
132 layer_size
+= slice
->size
* depth
;
135 image
->layer_size
= align(layer_size
, 4096);
139 tu_image_create(VkDevice _device
,
140 const struct tu_image_create_info
*create_info
,
141 const VkAllocationCallbacks
*alloc
,
144 TU_FROM_HANDLE(tu_device
, device
, _device
);
145 const VkImageCreateInfo
*pCreateInfo
= create_info
->vk_info
;
146 struct tu_image
*image
= NULL
;
147 assert(pCreateInfo
->sType
== VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO
);
149 tu_assert(pCreateInfo
->mipLevels
> 0);
150 tu_assert(pCreateInfo
->arrayLayers
> 0);
151 tu_assert(pCreateInfo
->samples
> 0);
152 tu_assert(pCreateInfo
->extent
.width
> 0);
153 tu_assert(pCreateInfo
->extent
.height
> 0);
154 tu_assert(pCreateInfo
->extent
.depth
> 0);
156 image
= vk_zalloc2(&device
->alloc
, alloc
, sizeof(*image
), 8,
157 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
159 return vk_error(device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
161 image
->type
= pCreateInfo
->imageType
;
163 image
->vk_format
= pCreateInfo
->format
;
164 image
->tiling
= pCreateInfo
->tiling
;
165 image
->usage
= pCreateInfo
->usage
;
166 image
->flags
= pCreateInfo
->flags
;
167 image
->extent
= pCreateInfo
->extent
;
168 image
->level_count
= pCreateInfo
->mipLevels
;
169 image
->layer_count
= pCreateInfo
->arrayLayers
;
170 image
->samples
= pCreateInfo
->samples
;
171 image
->cpp
= vk_format_get_blocksize(image
->vk_format
) * image
->samples
;
173 image
->exclusive
= pCreateInfo
->sharingMode
== VK_SHARING_MODE_EXCLUSIVE
;
174 if (pCreateInfo
->sharingMode
== VK_SHARING_MODE_CONCURRENT
) {
175 for (uint32_t i
= 0; i
< pCreateInfo
->queueFamilyIndexCount
; ++i
)
176 if (pCreateInfo
->pQueueFamilyIndices
[i
] ==
177 VK_QUEUE_FAMILY_EXTERNAL
)
178 image
->queue_family_mask
|= (1u << TU_MAX_QUEUE_FAMILIES
) - 1u;
180 image
->queue_family_mask
|=
181 1u << pCreateInfo
->pQueueFamilyIndices
[i
];
185 vk_find_struct_const(pCreateInfo
->pNext
,
186 EXTERNAL_MEMORY_IMAGE_CREATE_INFO
) != NULL
;
188 image
->tile_mode
= TILE6_3
;
190 if (pCreateInfo
->tiling
== VK_IMAGE_TILING_LINEAR
||
191 /* compressed textures can't use tiling? */
192 vk_format_is_compressed(image
->vk_format
) ||
193 /* scanout needs to be linear (what about tiling modifiers?) */
194 create_info
->scanout
||
195 /* image_to_image copy doesn't deal with tiling+swap */
196 tu6_get_native_format(image
->vk_format
)->swap
||
197 /* r8g8 formats are tiled different and could break image_to_image copy */
198 (image
->cpp
== 2 && vk_format_get_nr_components(image
->vk_format
) == 2))
199 image
->tile_mode
= TILE6_LINEAR
;
201 setup_slices(image
, pCreateInfo
);
203 image
->size
= image
->layer_size
* pCreateInfo
->arrayLayers
;
204 *pImage
= tu_image_to_handle(image
);
209 static enum a6xx_tex_fetchsize
210 tu6_fetchsize(VkFormat format
)
212 if (vk_format_description(format
)->layout
== VK_FORMAT_LAYOUT_ASTC
)
213 return TFETCH6_16_BYTE
;
215 switch (vk_format_get_blocksize(format
) / vk_format_get_blockwidth(format
)) {
216 case 1: return TFETCH6_1_BYTE
;
217 case 2: return TFETCH6_2_BYTE
;
218 case 4: return TFETCH6_4_BYTE
;
219 case 8: return TFETCH6_8_BYTE
;
220 case 16: return TFETCH6_16_BYTE
;
222 unreachable("bad block size");
227 tu6_texswiz(const VkComponentMapping
*comps
, const unsigned char *fmt_swiz
)
229 unsigned char swiz
[4] = {comps
->r
, comps
->g
, comps
->b
, comps
->a
};
230 unsigned char vk_swizzle
[] = {
231 [VK_COMPONENT_SWIZZLE_ZERO
] = A6XX_TEX_ZERO
,
232 [VK_COMPONENT_SWIZZLE_ONE
] = A6XX_TEX_ONE
,
233 [VK_COMPONENT_SWIZZLE_R
] = A6XX_TEX_X
,
234 [VK_COMPONENT_SWIZZLE_G
] = A6XX_TEX_Y
,
235 [VK_COMPONENT_SWIZZLE_B
] = A6XX_TEX_Z
,
236 [VK_COMPONENT_SWIZZLE_A
] = A6XX_TEX_W
,
238 for (unsigned i
= 0; i
< 4; i
++) {
239 swiz
[i
] = (swiz
[i
] == VK_COMPONENT_SWIZZLE_IDENTITY
) ? i
: vk_swizzle
[swiz
[i
]];
240 /* if format has 0/1 in channel, use that (needed for bc1_rgb) */
242 switch (fmt_swiz
[swiz
[i
]]) {
243 case VK_SWIZZLE_0
: swiz
[i
] = A6XX_TEX_ZERO
; break;
244 case VK_SWIZZLE_1
: swiz
[i
] = A6XX_TEX_ONE
; break;
249 return A6XX_TEX_CONST_0_SWIZ_X(swiz
[0]) |
250 A6XX_TEX_CONST_0_SWIZ_Y(swiz
[1]) |
251 A6XX_TEX_CONST_0_SWIZ_Z(swiz
[2]) |
252 A6XX_TEX_CONST_0_SWIZ_W(swiz
[3]);
255 static enum a6xx_tex_type
256 tu6_tex_type(VkImageViewType type
)
260 case VK_IMAGE_VIEW_TYPE_1D
:
261 case VK_IMAGE_VIEW_TYPE_1D_ARRAY
:
263 case VK_IMAGE_VIEW_TYPE_2D
:
264 case VK_IMAGE_VIEW_TYPE_2D_ARRAY
:
266 case VK_IMAGE_VIEW_TYPE_3D
:
268 case VK_IMAGE_VIEW_TYPE_CUBE
:
269 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY
:
270 return A6XX_TEX_CUBE
;
275 tu_image_view_init(struct tu_image_view
*iview
,
276 struct tu_device
*device
,
277 const VkImageViewCreateInfo
*pCreateInfo
)
279 TU_FROM_HANDLE(tu_image
, image
, pCreateInfo
->image
);
280 const VkImageSubresourceRange
*range
= &pCreateInfo
->subresourceRange
;
282 switch (image
->type
) {
283 case VK_IMAGE_TYPE_1D
:
284 case VK_IMAGE_TYPE_2D
:
285 assert(range
->baseArrayLayer
+ tu_get_layerCount(image
, range
) <=
288 case VK_IMAGE_TYPE_3D
:
289 assert(range
->baseArrayLayer
+ tu_get_layerCount(image
, range
) <=
290 tu_minify(image
->extent
.depth
, range
->baseMipLevel
));
293 unreachable("bad VkImageType");
296 iview
->image
= image
;
297 iview
->type
= pCreateInfo
->viewType
;
298 iview
->vk_format
= pCreateInfo
->format
;
299 iview
->aspect_mask
= pCreateInfo
->subresourceRange
.aspectMask
;
301 if (iview
->aspect_mask
== VK_IMAGE_ASPECT_STENCIL_BIT
) {
302 iview
->vk_format
= vk_format_stencil_only(iview
->vk_format
);
303 } else if (iview
->aspect_mask
== VK_IMAGE_ASPECT_DEPTH_BIT
) {
304 iview
->vk_format
= vk_format_depth_only(iview
->vk_format
);
308 iview
->extent
= image
->extent
;
310 iview
->base_layer
= range
->baseArrayLayer
;
311 iview
->layer_count
= tu_get_layerCount(image
, range
);
312 iview
->base_mip
= range
->baseMipLevel
;
313 iview
->level_count
= tu_get_levelCount(image
, range
);
315 memset(iview
->descriptor
, 0, sizeof(iview
->descriptor
));
317 const struct tu_native_format
*fmt
= tu6_get_native_format(iview
->vk_format
);
318 struct tu_image_level
*slice0
= &image
->levels
[iview
->base_mip
];
319 uint64_t base_addr
= image
->bo
->iova
+ iview
->base_layer
* image
->layer_size
+ slice0
->offset
;
320 uint32_t pitch
= (slice0
->pitch
/ vk_format_get_blockwidth(iview
->vk_format
)) *
321 vk_format_get_blocksize(iview
->vk_format
);
322 enum a6xx_tile_mode tile_mode
=
323 image_level_linear(image
, iview
->base_mip
) ? TILE6_LINEAR
: image
->tile_mode
;
325 iview
->descriptor
[0] =
326 A6XX_TEX_CONST_0_TILE_MODE(tile_mode
) |
327 COND(vk_format_is_srgb(iview
->vk_format
), A6XX_TEX_CONST_0_SRGB
) |
328 A6XX_TEX_CONST_0_FMT(fmt
->tex
) |
329 A6XX_TEX_CONST_0_SAMPLES(0) |
330 A6XX_TEX_CONST_0_SWAP(image
->tile_mode
? WZYX
: fmt
->swap
) |
331 tu6_texswiz(&pCreateInfo
->components
, vk_format_description(iview
->vk_format
)->swizzle
) |
332 A6XX_TEX_CONST_0_MIPLVLS(iview
->level_count
- 1);
333 iview
->descriptor
[1] =
334 A6XX_TEX_CONST_1_WIDTH(u_minify(image
->extent
.width
, iview
->base_mip
)) |
335 A6XX_TEX_CONST_1_HEIGHT(u_minify(image
->extent
.height
, iview
->base_mip
));
336 iview
->descriptor
[2] =
337 A6XX_TEX_CONST_2_FETCHSIZE(tu6_fetchsize(iview
->vk_format
)) |
338 A6XX_TEX_CONST_2_PITCH(pitch
) |
339 A6XX_TEX_CONST_2_TYPE(tu6_tex_type(pCreateInfo
->viewType
));
340 iview
->descriptor
[3] = 0;
341 iview
->descriptor
[4] = base_addr
;
342 iview
->descriptor
[5] = base_addr
>> 32;
344 if (pCreateInfo
->viewType
!= VK_IMAGE_VIEW_TYPE_3D
) {
345 iview
->descriptor
[3] |= A6XX_TEX_CONST_3_ARRAY_PITCH(image
->layer_size
);
346 iview
->descriptor
[5] |= A6XX_TEX_CONST_5_DEPTH(iview
->layer_count
);
348 iview
->descriptor
[3] |=
349 A6XX_TEX_CONST_3_MIN_LAYERSZ(image
->levels
[image
->level_count
- 1].size
) |
350 A6XX_TEX_CONST_3_ARRAY_PITCH(slice0
->size
);
351 iview
->descriptor
[5] |=
352 A6XX_TEX_CONST_5_DEPTH(u_minify(image
->extent
.depth
, iview
->base_mip
));
357 tu_image_queue_family_mask(const struct tu_image
*image
,
359 uint32_t queue_family
)
361 if (!image
->exclusive
)
362 return image
->queue_family_mask
;
363 if (family
== VK_QUEUE_FAMILY_EXTERNAL
)
364 return (1u << TU_MAX_QUEUE_FAMILIES
) - 1u;
365 if (family
== VK_QUEUE_FAMILY_IGNORED
)
366 return 1u << queue_family
;
371 tu_CreateImage(VkDevice device
,
372 const VkImageCreateInfo
*pCreateInfo
,
373 const VkAllocationCallbacks
*pAllocator
,
377 const VkNativeBufferANDROID
*gralloc_info
=
378 vk_find_struct_const(pCreateInfo
->pNext
, NATIVE_BUFFER_ANDROID
);
381 return tu_image_from_gralloc(device
, pCreateInfo
, gralloc_info
,
385 const struct wsi_image_create_info
*wsi_info
=
386 vk_find_struct_const(pCreateInfo
->pNext
, WSI_IMAGE_CREATE_INFO_MESA
);
387 bool scanout
= wsi_info
&& wsi_info
->scanout
;
389 return tu_image_create(device
,
390 &(struct tu_image_create_info
) {
391 .vk_info
= pCreateInfo
,
398 tu_DestroyImage(VkDevice _device
,
400 const VkAllocationCallbacks
*pAllocator
)
402 TU_FROM_HANDLE(tu_device
, device
, _device
);
403 TU_FROM_HANDLE(tu_image
, image
, _image
);
408 if (image
->owned_memory
!= VK_NULL_HANDLE
)
409 tu_FreeMemory(_device
, image
->owned_memory
, pAllocator
);
411 vk_free2(&device
->alloc
, pAllocator
, image
);
415 tu_GetImageSubresourceLayout(VkDevice _device
,
417 const VkImageSubresource
*pSubresource
,
418 VkSubresourceLayout
*pLayout
)
420 TU_FROM_HANDLE(tu_image
, image
, _image
);
422 const uint32_t layer_offset
= image
->layer_size
* pSubresource
->arrayLayer
;
423 const struct tu_image_level
*level
=
424 image
->levels
+ pSubresource
->mipLevel
;
426 pLayout
->offset
= layer_offset
+ level
->offset
;
427 pLayout
->size
= level
->size
;
429 level
->pitch
* vk_format_get_blocksize(image
->vk_format
);
430 pLayout
->arrayPitch
= image
->layer_size
;
431 pLayout
->depthPitch
= level
->size
;
435 tu_CreateImageView(VkDevice _device
,
436 const VkImageViewCreateInfo
*pCreateInfo
,
437 const VkAllocationCallbacks
*pAllocator
,
440 TU_FROM_HANDLE(tu_device
, device
, _device
);
441 struct tu_image_view
*view
;
443 view
= vk_alloc2(&device
->alloc
, pAllocator
, sizeof(*view
), 8,
444 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
446 return vk_error(device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
448 tu_image_view_init(view
, device
, pCreateInfo
);
450 *pView
= tu_image_view_to_handle(view
);
456 tu_DestroyImageView(VkDevice _device
,
458 const VkAllocationCallbacks
*pAllocator
)
460 TU_FROM_HANDLE(tu_device
, device
, _device
);
461 TU_FROM_HANDLE(tu_image_view
, iview
, _iview
);
465 vk_free2(&device
->alloc
, pAllocator
, iview
);
469 tu_buffer_view_init(struct tu_buffer_view
*view
,
470 struct tu_device
*device
,
471 const VkBufferViewCreateInfo
*pCreateInfo
)
473 TU_FROM_HANDLE(tu_buffer
, buffer
, pCreateInfo
->buffer
);
475 view
->range
= pCreateInfo
->range
== VK_WHOLE_SIZE
476 ? buffer
->size
- pCreateInfo
->offset
477 : pCreateInfo
->range
;
478 view
->vk_format
= pCreateInfo
->format
;
482 tu_CreateBufferView(VkDevice _device
,
483 const VkBufferViewCreateInfo
*pCreateInfo
,
484 const VkAllocationCallbacks
*pAllocator
,
487 TU_FROM_HANDLE(tu_device
, device
, _device
);
488 struct tu_buffer_view
*view
;
490 view
= vk_alloc2(&device
->alloc
, pAllocator
, sizeof(*view
), 8,
491 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
493 return vk_error(device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
495 tu_buffer_view_init(view
, device
, pCreateInfo
);
497 *pView
= tu_buffer_view_to_handle(view
);
503 tu_DestroyBufferView(VkDevice _device
,
504 VkBufferView bufferView
,
505 const VkAllocationCallbacks
*pAllocator
)
507 TU_FROM_HANDLE(tu_device
, device
, _device
);
508 TU_FROM_HANDLE(tu_buffer_view
, view
, bufferView
);
513 vk_free2(&device
->alloc
, pAllocator
, view
);