turnip: align layer_size
[mesa.git] / src / freedreno / vulkan / tu_image.c
1 /*
2 * Copyright © 2016 Red Hat.
3 * Copyright © 2016 Bas Nieuwenhuizen
4 *
5 * based in part on anv driver which is:
6 * Copyright © 2015 Intel Corporation
7 *
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:
14 *
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
17 * Software.
18 *
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.
26 */
27
28 #include "tu_private.h"
29
30 #include "util/debug.h"
31 #include "util/u_atomic.h"
32 #include "vk_format.h"
33 #include "vk_util.h"
34
35 static inline bool
36 image_level_linear(struct tu_image *image, int level)
37 {
38 unsigned w = u_minify(image->extent.width, level);
39 return w < 16;
40 }
41
42 /* indexed by cpp: */
43 static const struct
44 {
45 unsigned pitchalign;
46 unsigned heightalign;
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 },
50 };
51
52 static void
53 setup_slices(struct tu_image *image, const VkImageCreateInfo *pCreateInfo)
54 {
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);
64
65 uint32_t heightalign = tile_alignment[cpp].heightalign;
66
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;
71 uint32_t blocks;
72 uint32_t pitchalign;
73
74 if (image->tile_mode && !linear_level) {
75 pitchalign = tile_alignment[cpp].pitchalign;
76 aligned_height = align(aligned_height, heightalign);
77 } else {
78 pitchalign = 64;
79
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
85 * may not be:
86 */
87 if ((level + 1 == pCreateInfo->mipLevels))
88 aligned_height = align(aligned_height, 32);
89 }
90
91 if (layout == VK_FORMAT_LAYOUT_ASTC)
92 slice->pitch = util_align_npot(
93 width,
94 pitchalign * vk_format_get_blockwidth(pCreateInfo->format));
95 else
96 slice->pitch = align(width, pitchalign);
97
98 slice->offset = layer_size;
99 blocks = vk_format_get_block_count(pCreateInfo->format, slice->pitch,
100 aligned_height);
101
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.
107 */
108 if (pCreateInfo->imageType == VK_IMAGE_TYPE_3D &&
109 (level == 1 ||
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);
114 else
115 slice->size = image->levels[level - 1].size;
116
117 layer_size += slice->size * depth;
118
119 width = u_minify(width, 1);
120 height = u_minify(height, 1);
121 depth = u_minify(depth, 1);
122 }
123
124 image->layer_size = align(layer_size, 4096);
125 }
126
127 VkResult
128 tu_image_create(VkDevice _device,
129 const struct tu_image_create_info *create_info,
130 const VkAllocationCallbacks *alloc,
131 VkImage *pImage)
132 {
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);
137
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);
144
145 image = vk_zalloc2(&device->alloc, alloc, sizeof(*image), 8,
146 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
147 if (!image)
148 return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
149
150 image->type = pCreateInfo->imageType;
151
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;
159
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;
166 else
167 image->queue_family_mask |=
168 1u << pCreateInfo->pQueueFamilyIndices[i];
169 }
170
171 image->shareable =
172 vk_find_struct_const(pCreateInfo->pNext,
173 EXTERNAL_MEMORY_IMAGE_CREATE_INFO) != NULL;
174
175 image->tile_mode = TILE6_LINEAR;
176 if (pCreateInfo->tiling == VK_IMAGE_TILING_OPTIMAL && !create_info->scanout)
177 image->tile_mode = TILE6_3;
178
179 setup_slices(image, pCreateInfo);
180
181 image->size = image->layer_size * pCreateInfo->arrayLayers;
182 *pImage = tu_image_to_handle(image);
183
184 return VK_SUCCESS;
185 }
186
187 static enum a6xx_tex_fetchsize
188 translate_fetchsize(uint32_t cpp)
189 {
190 switch (cpp) {
191 case 1: return TFETCH6_1_BYTE;
192 case 2: return TFETCH6_2_BYTE;
193 case 4: return TFETCH6_4_BYTE;
194 case 8: return TFETCH6_8_BYTE;
195 case 16: return TFETCH6_16_BYTE;
196 default:
197 unreachable("bad block size");
198 }
199 }
200
201 static enum a6xx_tex_swiz
202 translate_swiz(VkComponentSwizzle swiz, enum a6xx_tex_swiz ident)
203 {
204 switch (swiz) {
205 default:
206 case VK_COMPONENT_SWIZZLE_IDENTITY: return ident;
207 case VK_COMPONENT_SWIZZLE_R: return A6XX_TEX_X;
208 case VK_COMPONENT_SWIZZLE_G: return A6XX_TEX_Y;
209 case VK_COMPONENT_SWIZZLE_B: return A6XX_TEX_Z;
210 case VK_COMPONENT_SWIZZLE_A: return A6XX_TEX_W;
211 case VK_COMPONENT_SWIZZLE_ZERO: return A6XX_TEX_ZERO;
212 case VK_COMPONENT_SWIZZLE_ONE: return A6XX_TEX_ONE;
213 }
214 }
215
216 static enum a6xx_tex_type
217 translate_tex_type(VkImageViewType type)
218 {
219 switch (type) {
220 default:
221 case VK_IMAGE_VIEW_TYPE_1D:
222 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
223 return A6XX_TEX_1D;
224 case VK_IMAGE_VIEW_TYPE_2D:
225 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
226 return A6XX_TEX_2D;
227 case VK_IMAGE_VIEW_TYPE_3D:
228 return A6XX_TEX_3D;
229 case VK_IMAGE_VIEW_TYPE_CUBE:
230 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
231 return A6XX_TEX_CUBE;
232 }
233 }
234
235 void
236 tu_image_view_init(struct tu_image_view *iview,
237 struct tu_device *device,
238 const VkImageViewCreateInfo *pCreateInfo)
239 {
240 TU_FROM_HANDLE(tu_image, image, pCreateInfo->image);
241 const VkImageSubresourceRange *range = &pCreateInfo->subresourceRange;
242
243 switch (image->type) {
244 case VK_IMAGE_TYPE_1D:
245 case VK_IMAGE_TYPE_2D:
246 assert(range->baseArrayLayer + tu_get_layerCount(image, range) <=
247 image->layer_count);
248 break;
249 case VK_IMAGE_TYPE_3D:
250 assert(range->baseArrayLayer + tu_get_layerCount(image, range) <=
251 tu_minify(image->extent.depth, range->baseMipLevel));
252 break;
253 default:
254 unreachable("bad VkImageType");
255 }
256
257 iview->image = image;
258 iview->type = pCreateInfo->viewType;
259 iview->vk_format = pCreateInfo->format;
260 iview->aspect_mask = pCreateInfo->subresourceRange.aspectMask;
261
262 if (iview->aspect_mask == VK_IMAGE_ASPECT_STENCIL_BIT) {
263 iview->vk_format = vk_format_stencil_only(iview->vk_format);
264 } else if (iview->aspect_mask == VK_IMAGE_ASPECT_DEPTH_BIT) {
265 iview->vk_format = vk_format_depth_only(iview->vk_format);
266 }
267
268 // should we minify?
269 iview->extent = image->extent;
270
271 iview->base_layer = range->baseArrayLayer;
272 iview->layer_count = tu_get_layerCount(image, range);
273 iview->base_mip = range->baseMipLevel;
274 iview->level_count = tu_get_levelCount(image, range);
275
276 memset(iview->descriptor, 0, sizeof(iview->descriptor));
277
278 const struct tu_native_format *fmt = tu6_get_native_format(iview->vk_format);
279 assert(fmt && fmt->tex >= 0);
280
281 struct tu_image_level *slice0 = &image->levels[iview->base_mip];
282 uint32_t cpp = vk_format_get_blocksize(iview->vk_format);
283 uint32_t block_width = vk_format_get_blockwidth(iview->vk_format);
284 const VkComponentMapping *comps = &pCreateInfo->components;
285
286 iview->descriptor[0] =
287 A6XX_TEX_CONST_0_TILE_MODE(image->tile_mode) |
288 COND(vk_format_is_srgb(iview->vk_format), A6XX_TEX_CONST_0_SRGB) |
289 A6XX_TEX_CONST_0_FMT(fmt->tex) |
290 A6XX_TEX_CONST_0_SAMPLES(0) |
291 A6XX_TEX_CONST_0_SWAP(fmt->swap) |
292 A6XX_TEX_CONST_0_SWIZ_X(translate_swiz(comps->r, A6XX_TEX_X)) |
293 A6XX_TEX_CONST_0_SWIZ_Y(translate_swiz(comps->g, A6XX_TEX_Y)) |
294 A6XX_TEX_CONST_0_SWIZ_Z(translate_swiz(comps->b, A6XX_TEX_Z)) |
295 A6XX_TEX_CONST_0_SWIZ_W(translate_swiz(comps->a, A6XX_TEX_W)) |
296 A6XX_TEX_CONST_0_MIPLVLS(iview->level_count - 1);
297 iview->descriptor[1] =
298 A6XX_TEX_CONST_1_WIDTH(u_minify(image->extent.width, iview->base_mip)) |
299 A6XX_TEX_CONST_1_HEIGHT(u_minify(image->extent.height, iview->base_mip));
300 iview->descriptor[2] =
301 A6XX_TEX_CONST_2_FETCHSIZE(translate_fetchsize(cpp)) |
302 A6XX_TEX_CONST_2_PITCH(slice0->pitch / block_width * cpp) |
303 A6XX_TEX_CONST_2_TYPE(translate_tex_type(pCreateInfo->viewType));
304 if (pCreateInfo->viewType != VK_IMAGE_VIEW_TYPE_3D) {
305 iview->descriptor[3] = A6XX_TEX_CONST_3_ARRAY_PITCH(image->layer_size);
306 } else {
307 iview->descriptor[3] =
308 A6XX_TEX_CONST_3_MIN_LAYERSZ(image->levels[image->level_count - 1].size) |
309 A6XX_TEX_CONST_3_ARRAY_PITCH(slice0->size);
310 }
311 uint64_t base_addr = image->bo->iova + iview->base_layer * image->layer_size + slice0->offset;
312 iview->descriptor[4] = base_addr;
313 iview->descriptor[5] = base_addr >> 32 | A6XX_TEX_CONST_5_DEPTH(iview->layer_count);
314 }
315
316 unsigned
317 tu_image_queue_family_mask(const struct tu_image *image,
318 uint32_t family,
319 uint32_t queue_family)
320 {
321 if (!image->exclusive)
322 return image->queue_family_mask;
323 if (family == VK_QUEUE_FAMILY_EXTERNAL)
324 return (1u << TU_MAX_QUEUE_FAMILIES) - 1u;
325 if (family == VK_QUEUE_FAMILY_IGNORED)
326 return 1u << queue_family;
327 return 1u << family;
328 }
329
330 VkResult
331 tu_CreateImage(VkDevice device,
332 const VkImageCreateInfo *pCreateInfo,
333 const VkAllocationCallbacks *pAllocator,
334 VkImage *pImage)
335 {
336 #ifdef ANDROID
337 const VkNativeBufferANDROID *gralloc_info =
338 vk_find_struct_const(pCreateInfo->pNext, NATIVE_BUFFER_ANDROID);
339
340 if (gralloc_info)
341 return tu_image_from_gralloc(device, pCreateInfo, gralloc_info,
342 pAllocator, pImage);
343 #endif
344
345 const struct wsi_image_create_info *wsi_info =
346 vk_find_struct_const(pCreateInfo->pNext, WSI_IMAGE_CREATE_INFO_MESA);
347 bool scanout = wsi_info && wsi_info->scanout;
348
349 return tu_image_create(device,
350 &(struct tu_image_create_info) {
351 .vk_info = pCreateInfo,
352 .scanout = scanout,
353 },
354 pAllocator, pImage);
355 }
356
357 void
358 tu_DestroyImage(VkDevice _device,
359 VkImage _image,
360 const VkAllocationCallbacks *pAllocator)
361 {
362 TU_FROM_HANDLE(tu_device, device, _device);
363 TU_FROM_HANDLE(tu_image, image, _image);
364
365 if (!image)
366 return;
367
368 if (image->owned_memory != VK_NULL_HANDLE)
369 tu_FreeMemory(_device, image->owned_memory, pAllocator);
370
371 vk_free2(&device->alloc, pAllocator, image);
372 }
373
374 void
375 tu_GetImageSubresourceLayout(VkDevice _device,
376 VkImage _image,
377 const VkImageSubresource *pSubresource,
378 VkSubresourceLayout *pLayout)
379 {
380 TU_FROM_HANDLE(tu_image, image, _image);
381
382 const uint32_t layer_offset = image->layer_size * pSubresource->arrayLayer;
383 const struct tu_image_level *level =
384 image->levels + pSubresource->mipLevel;
385
386 pLayout->offset = layer_offset + level->offset;
387 pLayout->size = level->size;
388 pLayout->rowPitch =
389 level->pitch * vk_format_get_blocksize(image->vk_format);
390 pLayout->arrayPitch = image->layer_size;
391 pLayout->depthPitch = level->size;
392 }
393
394 VkResult
395 tu_CreateImageView(VkDevice _device,
396 const VkImageViewCreateInfo *pCreateInfo,
397 const VkAllocationCallbacks *pAllocator,
398 VkImageView *pView)
399 {
400 TU_FROM_HANDLE(tu_device, device, _device);
401 struct tu_image_view *view;
402
403 view = vk_alloc2(&device->alloc, pAllocator, sizeof(*view), 8,
404 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
405 if (view == NULL)
406 return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
407
408 tu_image_view_init(view, device, pCreateInfo);
409
410 *pView = tu_image_view_to_handle(view);
411
412 return VK_SUCCESS;
413 }
414
415 void
416 tu_DestroyImageView(VkDevice _device,
417 VkImageView _iview,
418 const VkAllocationCallbacks *pAllocator)
419 {
420 TU_FROM_HANDLE(tu_device, device, _device);
421 TU_FROM_HANDLE(tu_image_view, iview, _iview);
422
423 if (!iview)
424 return;
425 vk_free2(&device->alloc, pAllocator, iview);
426 }
427
428 void
429 tu_buffer_view_init(struct tu_buffer_view *view,
430 struct tu_device *device,
431 const VkBufferViewCreateInfo *pCreateInfo)
432 {
433 TU_FROM_HANDLE(tu_buffer, buffer, pCreateInfo->buffer);
434
435 view->range = pCreateInfo->range == VK_WHOLE_SIZE
436 ? buffer->size - pCreateInfo->offset
437 : pCreateInfo->range;
438 view->vk_format = pCreateInfo->format;
439 }
440
441 VkResult
442 tu_CreateBufferView(VkDevice _device,
443 const VkBufferViewCreateInfo *pCreateInfo,
444 const VkAllocationCallbacks *pAllocator,
445 VkBufferView *pView)
446 {
447 TU_FROM_HANDLE(tu_device, device, _device);
448 struct tu_buffer_view *view;
449
450 view = vk_alloc2(&device->alloc, pAllocator, sizeof(*view), 8,
451 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
452 if (!view)
453 return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
454
455 tu_buffer_view_init(view, device, pCreateInfo);
456
457 *pView = tu_buffer_view_to_handle(view);
458
459 return VK_SUCCESS;
460 }
461
462 void
463 tu_DestroyBufferView(VkDevice _device,
464 VkBufferView bufferView,
465 const VkAllocationCallbacks *pAllocator)
466 {
467 TU_FROM_HANDLE(tu_device, device, _device);
468 TU_FROM_HANDLE(tu_buffer_view, view, bufferView);
469
470 if (!view)
471 return;
472
473 vk_free2(&device->alloc, pAllocator, view);
474 }