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
= layer_size
;
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
= pCreateInfo
->tiling
== VK_IMAGE_TILING_OPTIMAL
? 3 : 0;
176 setup_slices(image
, pCreateInfo
);
178 image
->size
= image
->layer_size
* pCreateInfo
->arrayLayers
;
179 *pImage
= tu_image_to_handle(image
);
185 tu_image_view_init(struct tu_image_view
*iview
,
186 struct tu_device
*device
,
187 const VkImageViewCreateInfo
*pCreateInfo
)
189 TU_FROM_HANDLE(tu_image
, image
, pCreateInfo
->image
);
190 const VkImageSubresourceRange
*range
= &pCreateInfo
->subresourceRange
;
192 switch (image
->type
) {
193 case VK_IMAGE_TYPE_1D
:
194 case VK_IMAGE_TYPE_2D
:
195 assert(range
->baseArrayLayer
+ tu_get_layerCount(image
, range
) <=
198 case VK_IMAGE_TYPE_3D
:
199 assert(range
->baseArrayLayer
+ tu_get_layerCount(image
, range
) <=
200 tu_minify(image
->extent
.depth
, range
->baseMipLevel
));
203 unreachable("bad VkImageType");
206 iview
->image
= image
;
207 iview
->type
= pCreateInfo
->viewType
;
208 iview
->vk_format
= pCreateInfo
->format
;
209 iview
->aspect_mask
= pCreateInfo
->subresourceRange
.aspectMask
;
211 if (iview
->aspect_mask
== VK_IMAGE_ASPECT_STENCIL_BIT
) {
212 iview
->vk_format
= vk_format_stencil_only(iview
->vk_format
);
213 } else if (iview
->aspect_mask
== VK_IMAGE_ASPECT_DEPTH_BIT
) {
214 iview
->vk_format
= vk_format_depth_only(iview
->vk_format
);
218 iview
->extent
= image
->extent
;
220 iview
->base_layer
= range
->baseArrayLayer
;
221 iview
->layer_count
= tu_get_layerCount(image
, range
);
222 iview
->base_mip
= range
->baseMipLevel
;
223 iview
->level_count
= tu_get_levelCount(image
, range
);
227 tu_image_queue_family_mask(const struct tu_image
*image
,
229 uint32_t queue_family
)
231 if (!image
->exclusive
)
232 return image
->queue_family_mask
;
233 if (family
== VK_QUEUE_FAMILY_EXTERNAL
)
234 return (1u << TU_MAX_QUEUE_FAMILIES
) - 1u;
235 if (family
== VK_QUEUE_FAMILY_IGNORED
)
236 return 1u << queue_family
;
241 tu_CreateImage(VkDevice device
,
242 const VkImageCreateInfo
*pCreateInfo
,
243 const VkAllocationCallbacks
*pAllocator
,
247 const VkNativeBufferANDROID
*gralloc_info
=
248 vk_find_struct_const(pCreateInfo
->pNext
, NATIVE_BUFFER_ANDROID
);
251 return tu_image_from_gralloc(device
, pCreateInfo
, gralloc_info
,
255 return tu_image_create(device
,
256 &(struct tu_image_create_info
) {
257 .vk_info
= pCreateInfo
,
264 tu_DestroyImage(VkDevice _device
,
266 const VkAllocationCallbacks
*pAllocator
)
268 TU_FROM_HANDLE(tu_device
, device
, _device
);
269 TU_FROM_HANDLE(tu_image
, image
, _image
);
274 if (image
->owned_memory
!= VK_NULL_HANDLE
)
275 tu_FreeMemory(_device
, image
->owned_memory
, pAllocator
);
277 vk_free2(&device
->alloc
, pAllocator
, image
);
281 tu_GetImageSubresourceLayout(VkDevice _device
,
283 const VkImageSubresource
*pSubresource
,
284 VkSubresourceLayout
*pLayout
)
286 TU_FROM_HANDLE(tu_image
, image
, _image
);
288 const uint32_t layer_offset
= image
->layer_size
* pSubresource
->arrayLayer
;
289 const struct tu_image_level
*level
=
290 image
->levels
+ pSubresource
->mipLevel
;
292 pLayout
->offset
= layer_offset
+ level
->offset
;
293 pLayout
->size
= level
->size
;
295 level
->pitch
* vk_format_get_blocksize(image
->vk_format
);
296 pLayout
->arrayPitch
= image
->layer_size
;
297 pLayout
->depthPitch
= level
->size
;
301 tu_CreateImageView(VkDevice _device
,
302 const VkImageViewCreateInfo
*pCreateInfo
,
303 const VkAllocationCallbacks
*pAllocator
,
306 TU_FROM_HANDLE(tu_device
, device
, _device
);
307 struct tu_image_view
*view
;
309 view
= vk_alloc2(&device
->alloc
, pAllocator
, sizeof(*view
), 8,
310 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
312 return vk_error(device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
314 tu_image_view_init(view
, device
, pCreateInfo
);
316 *pView
= tu_image_view_to_handle(view
);
322 tu_DestroyImageView(VkDevice _device
,
324 const VkAllocationCallbacks
*pAllocator
)
326 TU_FROM_HANDLE(tu_device
, device
, _device
);
327 TU_FROM_HANDLE(tu_image_view
, iview
, _iview
);
331 vk_free2(&device
->alloc
, pAllocator
, iview
);
335 tu_buffer_view_init(struct tu_buffer_view
*view
,
336 struct tu_device
*device
,
337 const VkBufferViewCreateInfo
*pCreateInfo
)
339 TU_FROM_HANDLE(tu_buffer
, buffer
, pCreateInfo
->buffer
);
341 view
->range
= pCreateInfo
->range
== VK_WHOLE_SIZE
342 ? buffer
->size
- pCreateInfo
->offset
343 : pCreateInfo
->range
;
344 view
->vk_format
= pCreateInfo
->format
;
348 tu_CreateBufferView(VkDevice _device
,
349 const VkBufferViewCreateInfo
*pCreateInfo
,
350 const VkAllocationCallbacks
*pAllocator
,
353 TU_FROM_HANDLE(tu_device
, device
, _device
);
354 struct tu_buffer_view
*view
;
356 view
= vk_alloc2(&device
->alloc
, pAllocator
, sizeof(*view
), 8,
357 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
359 return vk_error(device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
361 tu_buffer_view_init(view
, device
, pCreateInfo
);
363 *pView
= tu_buffer_view_to_handle(view
);
369 tu_DestroyBufferView(VkDevice _device
,
370 VkBufferView bufferView
,
371 const VkAllocationCallbacks
*pAllocator
)
373 TU_FROM_HANDLE(tu_device
, device
, _device
);
374 TU_FROM_HANDLE(tu_buffer_view
, view
, bufferView
);
379 vk_free2(&device
->alloc
, pAllocator
, view
);