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 DEALINGS
28 #include "tu_private.h"
29 #include "util/debug.h"
30 #include "util/u_atomic.h"
31 #include "vk_format.h"
36 image_level_linear(struct tu_image
*image
, int level
)
38 unsigned w
= u_minify(image
->extent
.width
, level
);
46 } tile_alignment
[] = {
57 setup_slices(struct tu_image
*image
, const VkImageCreateInfo
*pCreateInfo
)
59 enum vk_format_layout layout
= vk_format_description(pCreateInfo
->format
)->layout
;
60 uint32_t layer_size
= 0;
61 uint32_t width
= pCreateInfo
->extent
.width
;
62 uint32_t height
= pCreateInfo
->extent
.height
;
63 uint32_t depth
= pCreateInfo
->extent
.depth
;
64 bool layer_first
= pCreateInfo
->imageType
!= VK_IMAGE_TYPE_3D
;
65 uint32_t alignment
= pCreateInfo
->imageType
== VK_IMAGE_TYPE_3D
? 4096 : 1;
66 uint32_t cpp
= vk_format_get_blocksize(pCreateInfo
->format
);
68 uint32_t heightalign
= tile_alignment
[cpp
].heightalign
;
70 for (unsigned level
= 0; level
< pCreateInfo
->mipLevels
; level
++) {
71 struct tu_image_level
*slice
= &image
->levels
[level
];
72 bool linear_level
= image_level_linear(image
, level
);
73 uint32_t aligned_height
= height
;
77 if (image
->tile_mode
&& !linear_level
) {
78 pitchalign
= tile_alignment
[cpp
].pitchalign
;
79 aligned_height
= align(aligned_height
, heightalign
);
83 /* The blits used for mem<->gmem work at a granularity of
84 * 32x32, which can cause faults due to over-fetch on the
85 * last level. The simple solution is to over-allocate a
86 * bit the last level to ensure any over-fetch is harmless.
87 * The pitch is already sufficiently aligned, but height
90 if ((level
+ 1 == pCreateInfo
->mipLevels
))
91 aligned_height
= align(aligned_height
, 32);
94 if (layout
== VK_FORMAT_LAYOUT_ASTC
)
96 util_align_npot(width
, pitchalign
* vk_format_get_blockwidth(pCreateInfo
->format
));
98 slice
->pitch
= align(width
, pitchalign
);
100 slice
->offset
= layer_size
;
101 blocks
= vk_format_get_block_count(pCreateInfo
->format
, slice
->pitch
, aligned_height
);
103 /* 1d array and 2d array textures must all have the same layer size
104 * for each miplevel on a3xx. 3d textures can have different layer
105 * sizes for high levels, but the hw auto-sizer is buggy (or at least
106 * different than what this code does), so as soon as the layer size
107 * range gets into range, we stop reducing it.
109 if (pCreateInfo
->imageType
== VK_IMAGE_TYPE_3D
&& (
111 (level
> 1 && image
->levels
[level
- 1].size
> 0xf000)))
112 slice
->size
= align(blocks
* cpp
, alignment
);
113 else if (level
== 0 || layer_first
|| alignment
== 1)
114 slice
->size
= align(blocks
* cpp
, alignment
);
116 slice
->size
= image
->levels
[level
- 1].size
;
118 layer_size
+= slice
->size
* depth
;
120 width
= u_minify(width
, 1);
121 height
= u_minify(height
, 1);
122 depth
= u_minify(depth
, 1);
125 image
->layer_size
= layer_size
;
130 tu_image_create(VkDevice _device
,
131 const struct tu_image_create_info
*create_info
,
132 const VkAllocationCallbacks
*alloc
,
135 TU_FROM_HANDLE(tu_device
, device
, _device
);
136 const VkImageCreateInfo
*pCreateInfo
= create_info
->vk_info
;
137 struct tu_image
*image
= NULL
;
138 assert(pCreateInfo
->sType
== VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO
);
140 tu_assert(pCreateInfo
->mipLevels
> 0);
141 tu_assert(pCreateInfo
->arrayLayers
> 0);
142 tu_assert(pCreateInfo
->samples
> 0);
143 tu_assert(pCreateInfo
->extent
.width
> 0);
144 tu_assert(pCreateInfo
->extent
.height
> 0);
145 tu_assert(pCreateInfo
->extent
.depth
> 0);
147 image
= vk_zalloc2(&device
->alloc
,
151 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
153 return vk_error(device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
155 image
->type
= pCreateInfo
->imageType
;
157 image
->vk_format
= pCreateInfo
->format
;
158 image
->tiling
= pCreateInfo
->tiling
;
159 image
->usage
= pCreateInfo
->usage
;
160 image
->flags
= pCreateInfo
->flags
;
161 image
->extent
= pCreateInfo
->extent
;
163 image
->exclusive
= pCreateInfo
->sharingMode
== VK_SHARING_MODE_EXCLUSIVE
;
164 if (pCreateInfo
->sharingMode
== VK_SHARING_MODE_CONCURRENT
) {
165 for (uint32_t i
= 0; i
< pCreateInfo
->queueFamilyIndexCount
; ++i
)
166 if (pCreateInfo
->pQueueFamilyIndices
[i
] ==
167 VK_QUEUE_FAMILY_EXTERNAL_KHR
)
168 image
->queue_family_mask
|= (1u << TU_MAX_QUEUE_FAMILIES
) - 1u;
170 image
->queue_family_mask
|= 1u
171 << pCreateInfo
->pQueueFamilyIndices
[i
];
175 vk_find_struct_const(pCreateInfo
->pNext
,
176 EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR
) != NULL
;
178 image
->tile_mode
= pCreateInfo
->tiling
== VK_IMAGE_TILING_OPTIMAL
? 3 : 0;
179 setup_slices(image
, pCreateInfo
);
181 image
->size
= image
->layer_size
* pCreateInfo
->arrayLayers
;
182 *pImage
= tu_image_to_handle(image
);
188 tu_image_view_init(struct tu_image_view
*iview
,
189 struct tu_device
*device
,
190 const VkImageViewCreateInfo
*pCreateInfo
)
195 tu_image_queue_family_mask(const struct tu_image
*image
,
197 uint32_t queue_family
)
199 if (!image
->exclusive
)
200 return image
->queue_family_mask
;
201 if (family
== VK_QUEUE_FAMILY_EXTERNAL_KHR
)
202 return (1u << TU_MAX_QUEUE_FAMILIES
) - 1u;
203 if (family
== VK_QUEUE_FAMILY_IGNORED
)
204 return 1u << queue_family
;
209 tu_CreateImage(VkDevice device
,
210 const VkImageCreateInfo
*pCreateInfo
,
211 const VkAllocationCallbacks
*pAllocator
,
215 const VkNativeBufferANDROID
*gralloc_info
=
216 vk_find_struct_const(pCreateInfo
->pNext
, NATIVE_BUFFER_ANDROID
);
219 return tu_image_from_gralloc(
220 device
, pCreateInfo
, gralloc_info
, pAllocator
, pImage
);
223 return tu_image_create(device
,
224 &(struct tu_image_create_info
) {
225 .vk_info
= pCreateInfo
,
233 tu_DestroyImage(VkDevice _device
,
235 const VkAllocationCallbacks
*pAllocator
)
237 TU_FROM_HANDLE(tu_device
, device
, _device
);
238 TU_FROM_HANDLE(tu_image
, image
, _image
);
243 if (image
->owned_memory
!= VK_NULL_HANDLE
)
244 tu_FreeMemory(_device
, image
->owned_memory
, pAllocator
);
246 vk_free2(&device
->alloc
, pAllocator
, image
);
250 tu_GetImageSubresourceLayout(VkDevice _device
,
252 const VkImageSubresource
*pSubresource
,
253 VkSubresourceLayout
*pLayout
)
258 tu_CreateImageView(VkDevice _device
,
259 const VkImageViewCreateInfo
*pCreateInfo
,
260 const VkAllocationCallbacks
*pAllocator
,
263 TU_FROM_HANDLE(tu_device
, device
, _device
);
264 struct tu_image_view
*view
;
266 view
= vk_alloc2(&device
->alloc
,
270 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
272 return vk_error(device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
274 tu_image_view_init(view
, device
, pCreateInfo
);
276 *pView
= tu_image_view_to_handle(view
);
282 tu_DestroyImageView(VkDevice _device
,
284 const VkAllocationCallbacks
*pAllocator
)
286 TU_FROM_HANDLE(tu_device
, device
, _device
);
287 TU_FROM_HANDLE(tu_image_view
, iview
, _iview
);
291 vk_free2(&device
->alloc
, pAllocator
, iview
);
295 tu_buffer_view_init(struct tu_buffer_view
*view
,
296 struct tu_device
*device
,
297 const VkBufferViewCreateInfo
*pCreateInfo
)
299 TU_FROM_HANDLE(tu_buffer
, buffer
, pCreateInfo
->buffer
);
301 view
->range
= pCreateInfo
->range
== VK_WHOLE_SIZE
302 ? buffer
->size
- pCreateInfo
->offset
303 : pCreateInfo
->range
;
304 view
->vk_format
= pCreateInfo
->format
;
308 tu_CreateBufferView(VkDevice _device
,
309 const VkBufferViewCreateInfo
*pCreateInfo
,
310 const VkAllocationCallbacks
*pAllocator
,
313 TU_FROM_HANDLE(tu_device
, device
, _device
);
314 struct tu_buffer_view
*view
;
316 view
= vk_alloc2(&device
->alloc
,
320 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
322 return vk_error(device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
324 tu_buffer_view_init(view
, device
, pCreateInfo
);
326 *pView
= tu_buffer_view_to_handle(view
);
332 tu_DestroyBufferView(VkDevice _device
,
333 VkBufferView bufferView
,
334 const VkAllocationCallbacks
*pAllocator
)
336 TU_FROM_HANDLE(tu_device
, device
, _device
);
337 TU_FROM_HANDLE(tu_buffer_view
, view
, bufferView
);
342 vk_free2(&device
->alloc
, pAllocator
, view
);