turnip: disable tiling as necessary
[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, including msaa 2x and 4x: */
43 static const struct {
44 unsigned pitchalign;
45 unsigned heightalign;
46 } tile_alignment[] = {
47 [1] = { 128, 32 },
48 [2] = { 128, 16 },
49 [3] = { 64, 32 },
50 [4] = { 64, 16 },
51 [6] = { 64, 16 },
52 [8] = { 64, 16 },
53 [12] = { 64, 16 },
54 [16] = { 64, 16 },
55 [24] = { 64, 16 },
56 [32] = { 64, 16 },
57 [48] = { 64, 16 },
58 [64] = { 64, 16 },
59
60 /* special case for r8g8: */
61 [0] = { 64, 32 },
62 };
63
64 static void
65 setup_slices(struct tu_image *image, const VkImageCreateInfo *pCreateInfo)
66 {
67 VkFormat format = pCreateInfo->format;
68 enum vk_format_layout layout = vk_format_description(format)->layout;
69 uint32_t layer_size = 0;
70 int ta = image->cpp;
71
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)
74 ta = 0;
75
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;
82 uint32_t blocks;
83 uint32_t pitchalign;
84
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);
90 }
91 pitchalign = tile_alignment[ta].pitchalign;
92 aligned_height = align(aligned_height, tile_alignment[ta].heightalign);
93 } else {
94 pitchalign = 64;
95 }
96
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
102 * may not be:
103 */
104 if (level + 1 == pCreateInfo->mipLevels)
105 aligned_height = align(aligned_height, 32);
106
107 if (layout == VK_FORMAT_LAYOUT_ASTC)
108 slice->pitch =
109 util_align_npot(width, pitchalign * vk_format_get_blockwidth(format));
110 else
111 slice->pitch = align(width, pitchalign);
112
113 slice->offset = layer_size;
114 blocks = vk_format_get_block_count(format, slice->pitch, aligned_height);
115
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.
121 */
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);
125 } else {
126 slice->size = image->levels[level - 1].size;
127 }
128 } else {
129 slice->size = blocks * image->cpp;
130 }
131
132 layer_size += slice->size * depth;
133 }
134
135 image->layer_size = align(layer_size, 4096);
136 }
137
138 VkResult
139 tu_image_create(VkDevice _device,
140 const struct tu_image_create_info *create_info,
141 const VkAllocationCallbacks *alloc,
142 VkImage *pImage)
143 {
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);
148
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);
155
156 image = vk_zalloc2(&device->alloc, alloc, sizeof(*image), 8,
157 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
158 if (!image)
159 return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
160
161 image->type = pCreateInfo->imageType;
162
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;
172
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;
179 else
180 image->queue_family_mask |=
181 1u << pCreateInfo->pQueueFamilyIndices[i];
182 }
183
184 image->shareable =
185 vk_find_struct_const(pCreateInfo->pNext,
186 EXTERNAL_MEMORY_IMAGE_CREATE_INFO) != NULL;
187
188 image->tile_mode = TILE6_3;
189
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;
200
201 setup_slices(image, pCreateInfo);
202
203 image->size = image->layer_size * pCreateInfo->arrayLayers;
204 *pImage = tu_image_to_handle(image);
205
206 return VK_SUCCESS;
207 }
208
209 static enum a6xx_tex_fetchsize
210 tu6_fetchsize(VkFormat format)
211 {
212 if (vk_format_description(format)->layout == VK_FORMAT_LAYOUT_ASTC)
213 return TFETCH6_16_BYTE;
214
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;
221 default:
222 unreachable("bad block size");
223 }
224 }
225
226 static uint32_t
227 tu6_texswiz(const VkComponentMapping *comps, const unsigned char *fmt_swiz)
228 {
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,
237 };
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) */
241 if (swiz[i] < 4) {
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;
245 }
246 }
247 }
248
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]);
253 }
254
255 static enum a6xx_tex_type
256 tu6_tex_type(VkImageViewType type)
257 {
258 switch (type) {
259 default:
260 case VK_IMAGE_VIEW_TYPE_1D:
261 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
262 return A6XX_TEX_1D;
263 case VK_IMAGE_VIEW_TYPE_2D:
264 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
265 return A6XX_TEX_2D;
266 case VK_IMAGE_VIEW_TYPE_3D:
267 return A6XX_TEX_3D;
268 case VK_IMAGE_VIEW_TYPE_CUBE:
269 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
270 return A6XX_TEX_CUBE;
271 }
272 }
273
274 void
275 tu_image_view_init(struct tu_image_view *iview,
276 struct tu_device *device,
277 const VkImageViewCreateInfo *pCreateInfo)
278 {
279 TU_FROM_HANDLE(tu_image, image, pCreateInfo->image);
280 const VkImageSubresourceRange *range = &pCreateInfo->subresourceRange;
281
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) <=
286 image->layer_count);
287 break;
288 case VK_IMAGE_TYPE_3D:
289 assert(range->baseArrayLayer + tu_get_layerCount(image, range) <=
290 tu_minify(image->extent.depth, range->baseMipLevel));
291 break;
292 default:
293 unreachable("bad VkImageType");
294 }
295
296 iview->image = image;
297 iview->type = pCreateInfo->viewType;
298 iview->vk_format = pCreateInfo->format;
299 iview->aspect_mask = pCreateInfo->subresourceRange.aspectMask;
300
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);
305 }
306
307 // should we minify?
308 iview->extent = image->extent;
309
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);
314
315 memset(iview->descriptor, 0, sizeof(iview->descriptor));
316
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;
324
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;
343
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);
347 } else {
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));
353 }
354 }
355
356 unsigned
357 tu_image_queue_family_mask(const struct tu_image *image,
358 uint32_t family,
359 uint32_t queue_family)
360 {
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;
367 return 1u << family;
368 }
369
370 VkResult
371 tu_CreateImage(VkDevice device,
372 const VkImageCreateInfo *pCreateInfo,
373 const VkAllocationCallbacks *pAllocator,
374 VkImage *pImage)
375 {
376 #ifdef ANDROID
377 const VkNativeBufferANDROID *gralloc_info =
378 vk_find_struct_const(pCreateInfo->pNext, NATIVE_BUFFER_ANDROID);
379
380 if (gralloc_info)
381 return tu_image_from_gralloc(device, pCreateInfo, gralloc_info,
382 pAllocator, pImage);
383 #endif
384
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;
388
389 return tu_image_create(device,
390 &(struct tu_image_create_info) {
391 .vk_info = pCreateInfo,
392 .scanout = scanout,
393 },
394 pAllocator, pImage);
395 }
396
397 void
398 tu_DestroyImage(VkDevice _device,
399 VkImage _image,
400 const VkAllocationCallbacks *pAllocator)
401 {
402 TU_FROM_HANDLE(tu_device, device, _device);
403 TU_FROM_HANDLE(tu_image, image, _image);
404
405 if (!image)
406 return;
407
408 if (image->owned_memory != VK_NULL_HANDLE)
409 tu_FreeMemory(_device, image->owned_memory, pAllocator);
410
411 vk_free2(&device->alloc, pAllocator, image);
412 }
413
414 void
415 tu_GetImageSubresourceLayout(VkDevice _device,
416 VkImage _image,
417 const VkImageSubresource *pSubresource,
418 VkSubresourceLayout *pLayout)
419 {
420 TU_FROM_HANDLE(tu_image, image, _image);
421
422 const uint32_t layer_offset = image->layer_size * pSubresource->arrayLayer;
423 const struct tu_image_level *level =
424 image->levels + pSubresource->mipLevel;
425
426 pLayout->offset = layer_offset + level->offset;
427 pLayout->size = level->size;
428 pLayout->rowPitch =
429 level->pitch * vk_format_get_blocksize(image->vk_format);
430 pLayout->arrayPitch = image->layer_size;
431 pLayout->depthPitch = level->size;
432 }
433
434 VkResult
435 tu_CreateImageView(VkDevice _device,
436 const VkImageViewCreateInfo *pCreateInfo,
437 const VkAllocationCallbacks *pAllocator,
438 VkImageView *pView)
439 {
440 TU_FROM_HANDLE(tu_device, device, _device);
441 struct tu_image_view *view;
442
443 view = vk_alloc2(&device->alloc, pAllocator, sizeof(*view), 8,
444 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
445 if (view == NULL)
446 return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
447
448 tu_image_view_init(view, device, pCreateInfo);
449
450 *pView = tu_image_view_to_handle(view);
451
452 return VK_SUCCESS;
453 }
454
455 void
456 tu_DestroyImageView(VkDevice _device,
457 VkImageView _iview,
458 const VkAllocationCallbacks *pAllocator)
459 {
460 TU_FROM_HANDLE(tu_device, device, _device);
461 TU_FROM_HANDLE(tu_image_view, iview, _iview);
462
463 if (!iview)
464 return;
465 vk_free2(&device->alloc, pAllocator, iview);
466 }
467
468 void
469 tu_buffer_view_init(struct tu_buffer_view *view,
470 struct tu_device *device,
471 const VkBufferViewCreateInfo *pCreateInfo)
472 {
473 TU_FROM_HANDLE(tu_buffer, buffer, pCreateInfo->buffer);
474
475 view->range = pCreateInfo->range == VK_WHOLE_SIZE
476 ? buffer->size - pCreateInfo->offset
477 : pCreateInfo->range;
478 view->vk_format = pCreateInfo->format;
479 }
480
481 VkResult
482 tu_CreateBufferView(VkDevice _device,
483 const VkBufferViewCreateInfo *pCreateInfo,
484 const VkAllocationCallbacks *pAllocator,
485 VkBufferView *pView)
486 {
487 TU_FROM_HANDLE(tu_device, device, _device);
488 struct tu_buffer_view *view;
489
490 view = vk_alloc2(&device->alloc, pAllocator, sizeof(*view), 8,
491 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
492 if (!view)
493 return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
494
495 tu_buffer_view_init(view, device, pCreateInfo);
496
497 *pView = tu_buffer_view_to_handle(view);
498
499 return VK_SUCCESS;
500 }
501
502 void
503 tu_DestroyBufferView(VkDevice _device,
504 VkBufferView bufferView,
505 const VkAllocationCallbacks *pAllocator)
506 {
507 TU_FROM_HANDLE(tu_device, device, _device);
508 TU_FROM_HANDLE(tu_buffer_view, view, bufferView);
509
510 if (!view)
511 return;
512
513 vk_free2(&device->alloc, pAllocator, view);
514 }