1b8e80941Smrg/*
2b8e80941Smrg * Copyright © 2016 Red Hat.
3b8e80941Smrg * Copyright © 2016 Bas Nieuwenhuizen
4b8e80941Smrg *
5b8e80941Smrg * based in part on anv driver which is:
6b8e80941Smrg * Copyright © 2015 Intel Corporation
7b8e80941Smrg *
8b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a
9b8e80941Smrg * copy of this software and associated documentation files (the "Software"),
10b8e80941Smrg * to deal in the Software without restriction, including without limitation
11b8e80941Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12b8e80941Smrg * and/or sell copies of the Software, and to permit persons to whom the
13b8e80941Smrg * Software is furnished to do so, subject to the following conditions:
14b8e80941Smrg *
15b8e80941Smrg * The above copyright notice and this permission notice (including the next
16b8e80941Smrg * paragraph) shall be included in all copies or substantial portions of the
17b8e80941Smrg * Software.
18b8e80941Smrg *
19b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20b8e80941Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
22b8e80941Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23b8e80941Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24b8e80941Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25b8e80941Smrg * DEALINGS IN THE SOFTWARE.
26b8e80941Smrg */
27b8e80941Smrg
28b8e80941Smrg#include "tu_private.h"
29b8e80941Smrg
30b8e80941Smrg#include "util/debug.h"
31b8e80941Smrg#include "util/u_atomic.h"
32b8e80941Smrg#include "vk_format.h"
33b8e80941Smrg#include "vk_util.h"
34b8e80941Smrg
35b8e80941Smrgstatic inline bool
36b8e80941Smrgimage_level_linear(struct tu_image *image, int level)
37b8e80941Smrg{
38b8e80941Smrg   unsigned w = u_minify(image->extent.width, level);
39b8e80941Smrg   return w < 16;
40b8e80941Smrg}
41b8e80941Smrg
42b8e80941Smrg/* indexed by cpp: */
43b8e80941Smrgstatic const struct
44b8e80941Smrg{
45b8e80941Smrg   unsigned pitchalign;
46b8e80941Smrg   unsigned heightalign;
47b8e80941Smrg} tile_alignment[] = {
48b8e80941Smrg   [1] = { 128, 32 }, [2] = { 128, 16 }, [3] = { 128, 16 }, [4] = { 64, 16 },
49b8e80941Smrg   [8] = { 64, 16 },  [12] = { 64, 16 }, [16] = { 64, 16 },
50b8e80941Smrg};
51b8e80941Smrg
52b8e80941Smrgstatic void
53b8e80941Smrgsetup_slices(struct tu_image *image, const VkImageCreateInfo *pCreateInfo)
54b8e80941Smrg{
55b8e80941Smrg   enum vk_format_layout layout =
56b8e80941Smrg      vk_format_description(pCreateInfo->format)->layout;
57b8e80941Smrg   uint32_t layer_size = 0;
58b8e80941Smrg   uint32_t width = pCreateInfo->extent.width;
59b8e80941Smrg   uint32_t height = pCreateInfo->extent.height;
60b8e80941Smrg   uint32_t depth = pCreateInfo->extent.depth;
61b8e80941Smrg   bool layer_first = pCreateInfo->imageType != VK_IMAGE_TYPE_3D;
62b8e80941Smrg   uint32_t alignment = pCreateInfo->imageType == VK_IMAGE_TYPE_3D ? 4096 : 1;
63b8e80941Smrg   uint32_t cpp = vk_format_get_blocksize(pCreateInfo->format);
64b8e80941Smrg
65b8e80941Smrg   uint32_t heightalign = tile_alignment[cpp].heightalign;
66b8e80941Smrg
67b8e80941Smrg   for (unsigned level = 0; level < pCreateInfo->mipLevels; level++) {
68b8e80941Smrg      struct tu_image_level *slice = &image->levels[level];
69b8e80941Smrg      bool linear_level = image_level_linear(image, level);
70b8e80941Smrg      uint32_t aligned_height = height;
71b8e80941Smrg      uint32_t blocks;
72b8e80941Smrg      uint32_t pitchalign;
73b8e80941Smrg
74b8e80941Smrg      if (image->tile_mode && !linear_level) {
75b8e80941Smrg         pitchalign = tile_alignment[cpp].pitchalign;
76b8e80941Smrg         aligned_height = align(aligned_height, heightalign);
77b8e80941Smrg      } else {
78b8e80941Smrg         pitchalign = 64;
79b8e80941Smrg
80b8e80941Smrg         /* The blits used for mem<->gmem work at a granularity of
81b8e80941Smrg          * 32x32, which can cause faults due to over-fetch on the
82b8e80941Smrg          * last level.  The simple solution is to over-allocate a
83b8e80941Smrg          * bit the last level to ensure any over-fetch is harmless.
84b8e80941Smrg          * The pitch is already sufficiently aligned, but height
85b8e80941Smrg          * may not be:
86b8e80941Smrg          */
87b8e80941Smrg         if ((level + 1 == pCreateInfo->mipLevels))
88b8e80941Smrg            aligned_height = align(aligned_height, 32);
89b8e80941Smrg      }
90b8e80941Smrg
91b8e80941Smrg      if (layout == VK_FORMAT_LAYOUT_ASTC)
92b8e80941Smrg         slice->pitch = util_align_npot(
93b8e80941Smrg            width,
94b8e80941Smrg            pitchalign * vk_format_get_blockwidth(pCreateInfo->format));
95b8e80941Smrg      else
96b8e80941Smrg         slice->pitch = align(width, pitchalign);
97b8e80941Smrg
98b8e80941Smrg      slice->offset = layer_size;
99b8e80941Smrg      blocks = vk_format_get_block_count(pCreateInfo->format, slice->pitch,
100b8e80941Smrg                                         aligned_height);
101b8e80941Smrg
102b8e80941Smrg      /* 1d array and 2d array textures must all have the same layer size
103b8e80941Smrg       * for each miplevel on a3xx. 3d textures can have different layer
104b8e80941Smrg       * sizes for high levels, but the hw auto-sizer is buggy (or at least
105b8e80941Smrg       * different than what this code does), so as soon as the layer size
106b8e80941Smrg       * range gets into range, we stop reducing it.
107b8e80941Smrg       */
108b8e80941Smrg      if (pCreateInfo->imageType == VK_IMAGE_TYPE_3D &&
109b8e80941Smrg          (level == 1 ||
110b8e80941Smrg           (level > 1 && image->levels[level - 1].size > 0xf000)))
111b8e80941Smrg         slice->size = align(blocks * cpp, alignment);
112b8e80941Smrg      else if (level == 0 || layer_first || alignment == 1)
113b8e80941Smrg         slice->size = align(blocks * cpp, alignment);
114b8e80941Smrg      else
115b8e80941Smrg         slice->size = image->levels[level - 1].size;
116b8e80941Smrg
117b8e80941Smrg      layer_size += slice->size * depth;
118b8e80941Smrg
119b8e80941Smrg      width = u_minify(width, 1);
120b8e80941Smrg      height = u_minify(height, 1);
121b8e80941Smrg      depth = u_minify(depth, 1);
122b8e80941Smrg   }
123b8e80941Smrg
124b8e80941Smrg   image->layer_size = layer_size;
125b8e80941Smrg}
126b8e80941Smrg
127b8e80941SmrgVkResult
128b8e80941Smrgtu_image_create(VkDevice _device,
129b8e80941Smrg                const struct tu_image_create_info *create_info,
130b8e80941Smrg                const VkAllocationCallbacks *alloc,
131b8e80941Smrg                VkImage *pImage)
132b8e80941Smrg{
133b8e80941Smrg   TU_FROM_HANDLE(tu_device, device, _device);
134b8e80941Smrg   const VkImageCreateInfo *pCreateInfo = create_info->vk_info;
135b8e80941Smrg   struct tu_image *image = NULL;
136b8e80941Smrg   assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO);
137b8e80941Smrg
138b8e80941Smrg   tu_assert(pCreateInfo->mipLevels > 0);
139b8e80941Smrg   tu_assert(pCreateInfo->arrayLayers > 0);
140b8e80941Smrg   tu_assert(pCreateInfo->samples > 0);
141b8e80941Smrg   tu_assert(pCreateInfo->extent.width > 0);
142b8e80941Smrg   tu_assert(pCreateInfo->extent.height > 0);
143b8e80941Smrg   tu_assert(pCreateInfo->extent.depth > 0);
144b8e80941Smrg
145b8e80941Smrg   image = vk_zalloc2(&device->alloc, alloc, sizeof(*image), 8,
146b8e80941Smrg                      VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
147b8e80941Smrg   if (!image)
148b8e80941Smrg      return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
149b8e80941Smrg
150b8e80941Smrg   image->type = pCreateInfo->imageType;
151b8e80941Smrg
152b8e80941Smrg   image->vk_format = pCreateInfo->format;
153b8e80941Smrg   image->tiling = pCreateInfo->tiling;
154b8e80941Smrg   image->usage = pCreateInfo->usage;
155b8e80941Smrg   image->flags = pCreateInfo->flags;
156b8e80941Smrg   image->extent = pCreateInfo->extent;
157b8e80941Smrg   image->level_count = pCreateInfo->mipLevels;
158b8e80941Smrg   image->layer_count = pCreateInfo->arrayLayers;
159b8e80941Smrg
160b8e80941Smrg   image->exclusive = pCreateInfo->sharingMode == VK_SHARING_MODE_EXCLUSIVE;
161b8e80941Smrg   if (pCreateInfo->sharingMode == VK_SHARING_MODE_CONCURRENT) {
162b8e80941Smrg      for (uint32_t i = 0; i < pCreateInfo->queueFamilyIndexCount; ++i)
163b8e80941Smrg         if (pCreateInfo->pQueueFamilyIndices[i] ==
164b8e80941Smrg             VK_QUEUE_FAMILY_EXTERNAL)
165b8e80941Smrg            image->queue_family_mask |= (1u << TU_MAX_QUEUE_FAMILIES) - 1u;
166b8e80941Smrg         else
167b8e80941Smrg            image->queue_family_mask |=
168b8e80941Smrg               1u << pCreateInfo->pQueueFamilyIndices[i];
169b8e80941Smrg   }
170b8e80941Smrg
171b8e80941Smrg   image->shareable =
172b8e80941Smrg      vk_find_struct_const(pCreateInfo->pNext,
173b8e80941Smrg                           EXTERNAL_MEMORY_IMAGE_CREATE_INFO) != NULL;
174b8e80941Smrg
175b8e80941Smrg   image->tile_mode = pCreateInfo->tiling == VK_IMAGE_TILING_OPTIMAL ? 3 : 0;
176b8e80941Smrg   setup_slices(image, pCreateInfo);
177b8e80941Smrg
178b8e80941Smrg   image->size = image->layer_size * pCreateInfo->arrayLayers;
179b8e80941Smrg   *pImage = tu_image_to_handle(image);
180b8e80941Smrg
181b8e80941Smrg   return VK_SUCCESS;
182b8e80941Smrg}
183b8e80941Smrg
184b8e80941Smrgvoid
185b8e80941Smrgtu_image_view_init(struct tu_image_view *iview,
186b8e80941Smrg                   struct tu_device *device,
187b8e80941Smrg                   const VkImageViewCreateInfo *pCreateInfo)
188b8e80941Smrg{
189b8e80941Smrg   TU_FROM_HANDLE(tu_image, image, pCreateInfo->image);
190b8e80941Smrg   const VkImageSubresourceRange *range = &pCreateInfo->subresourceRange;
191b8e80941Smrg
192b8e80941Smrg   switch (image->type) {
193b8e80941Smrg   case VK_IMAGE_TYPE_1D:
194b8e80941Smrg   case VK_IMAGE_TYPE_2D:
195b8e80941Smrg      assert(range->baseArrayLayer + tu_get_layerCount(image, range) <=
196b8e80941Smrg             image->layer_count);
197b8e80941Smrg      break;
198b8e80941Smrg   case VK_IMAGE_TYPE_3D:
199b8e80941Smrg      assert(range->baseArrayLayer + tu_get_layerCount(image, range) <=
200b8e80941Smrg             tu_minify(image->extent.depth, range->baseMipLevel));
201b8e80941Smrg      break;
202b8e80941Smrg   default:
203b8e80941Smrg      unreachable("bad VkImageType");
204b8e80941Smrg   }
205b8e80941Smrg
206b8e80941Smrg   iview->image = image;
207b8e80941Smrg   iview->type = pCreateInfo->viewType;
208b8e80941Smrg   iview->vk_format = pCreateInfo->format;
209b8e80941Smrg   iview->aspect_mask = pCreateInfo->subresourceRange.aspectMask;
210b8e80941Smrg
211b8e80941Smrg   if (iview->aspect_mask == VK_IMAGE_ASPECT_STENCIL_BIT) {
212b8e80941Smrg      iview->vk_format = vk_format_stencil_only(iview->vk_format);
213b8e80941Smrg   } else if (iview->aspect_mask == VK_IMAGE_ASPECT_DEPTH_BIT) {
214b8e80941Smrg      iview->vk_format = vk_format_depth_only(iview->vk_format);
215b8e80941Smrg   }
216b8e80941Smrg
217b8e80941Smrg   // should we minify?
218b8e80941Smrg   iview->extent = image->extent;
219b8e80941Smrg
220b8e80941Smrg   iview->base_layer = range->baseArrayLayer;
221b8e80941Smrg   iview->layer_count = tu_get_layerCount(image, range);
222b8e80941Smrg   iview->base_mip = range->baseMipLevel;
223b8e80941Smrg   iview->level_count = tu_get_levelCount(image, range);
224b8e80941Smrg}
225b8e80941Smrg
226b8e80941Smrgunsigned
227b8e80941Smrgtu_image_queue_family_mask(const struct tu_image *image,
228b8e80941Smrg                           uint32_t family,
229b8e80941Smrg                           uint32_t queue_family)
230b8e80941Smrg{
231b8e80941Smrg   if (!image->exclusive)
232b8e80941Smrg      return image->queue_family_mask;
233b8e80941Smrg   if (family == VK_QUEUE_FAMILY_EXTERNAL)
234b8e80941Smrg      return (1u << TU_MAX_QUEUE_FAMILIES) - 1u;
235b8e80941Smrg   if (family == VK_QUEUE_FAMILY_IGNORED)
236b8e80941Smrg      return 1u << queue_family;
237b8e80941Smrg   return 1u << family;
238b8e80941Smrg}
239b8e80941Smrg
240b8e80941SmrgVkResult
241b8e80941Smrgtu_CreateImage(VkDevice device,
242b8e80941Smrg               const VkImageCreateInfo *pCreateInfo,
243b8e80941Smrg               const VkAllocationCallbacks *pAllocator,
244b8e80941Smrg               VkImage *pImage)
245b8e80941Smrg{
246b8e80941Smrg#ifdef ANDROID
247b8e80941Smrg   const VkNativeBufferANDROID *gralloc_info =
248b8e80941Smrg      vk_find_struct_const(pCreateInfo->pNext, NATIVE_BUFFER_ANDROID);
249b8e80941Smrg
250b8e80941Smrg   if (gralloc_info)
251b8e80941Smrg      return tu_image_from_gralloc(device, pCreateInfo, gralloc_info,
252b8e80941Smrg                                   pAllocator, pImage);
253b8e80941Smrg#endif
254b8e80941Smrg
255b8e80941Smrg   return tu_image_create(device,
256b8e80941Smrg                          &(struct tu_image_create_info) {
257b8e80941Smrg                             .vk_info = pCreateInfo,
258b8e80941Smrg                             .scanout = false,
259b8e80941Smrg                          },
260b8e80941Smrg                          pAllocator, pImage);
261b8e80941Smrg}
262b8e80941Smrg
263b8e80941Smrgvoid
264b8e80941Smrgtu_DestroyImage(VkDevice _device,
265b8e80941Smrg                VkImage _image,
266b8e80941Smrg                const VkAllocationCallbacks *pAllocator)
267b8e80941Smrg{
268b8e80941Smrg   TU_FROM_HANDLE(tu_device, device, _device);
269b8e80941Smrg   TU_FROM_HANDLE(tu_image, image, _image);
270b8e80941Smrg
271b8e80941Smrg   if (!image)
272b8e80941Smrg      return;
273b8e80941Smrg
274b8e80941Smrg   if (image->owned_memory != VK_NULL_HANDLE)
275b8e80941Smrg      tu_FreeMemory(_device, image->owned_memory, pAllocator);
276b8e80941Smrg
277b8e80941Smrg   vk_free2(&device->alloc, pAllocator, image);
278b8e80941Smrg}
279b8e80941Smrg
280b8e80941Smrgvoid
281b8e80941Smrgtu_GetImageSubresourceLayout(VkDevice _device,
282b8e80941Smrg                             VkImage _image,
283b8e80941Smrg                             const VkImageSubresource *pSubresource,
284b8e80941Smrg                             VkSubresourceLayout *pLayout)
285b8e80941Smrg{
286b8e80941Smrg   TU_FROM_HANDLE(tu_image, image, _image);
287b8e80941Smrg
288b8e80941Smrg   const uint32_t layer_offset = image->layer_size * pSubresource->arrayLayer;
289b8e80941Smrg   const struct tu_image_level *level =
290b8e80941Smrg      image->levels + pSubresource->mipLevel;
291b8e80941Smrg
292b8e80941Smrg   pLayout->offset = layer_offset + level->offset;
293b8e80941Smrg   pLayout->size = level->size;
294b8e80941Smrg   pLayout->rowPitch =
295b8e80941Smrg      level->pitch * vk_format_get_blocksize(image->vk_format);
296b8e80941Smrg   pLayout->arrayPitch = image->layer_size;
297b8e80941Smrg   pLayout->depthPitch = level->size;
298b8e80941Smrg}
299b8e80941Smrg
300b8e80941SmrgVkResult
301b8e80941Smrgtu_CreateImageView(VkDevice _device,
302b8e80941Smrg                   const VkImageViewCreateInfo *pCreateInfo,
303b8e80941Smrg                   const VkAllocationCallbacks *pAllocator,
304b8e80941Smrg                   VkImageView *pView)
305b8e80941Smrg{
306b8e80941Smrg   TU_FROM_HANDLE(tu_device, device, _device);
307b8e80941Smrg   struct tu_image_view *view;
308b8e80941Smrg
309b8e80941Smrg   view = vk_alloc2(&device->alloc, pAllocator, sizeof(*view), 8,
310b8e80941Smrg                    VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
311b8e80941Smrg   if (view == NULL)
312b8e80941Smrg      return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
313b8e80941Smrg
314b8e80941Smrg   tu_image_view_init(view, device, pCreateInfo);
315b8e80941Smrg
316b8e80941Smrg   *pView = tu_image_view_to_handle(view);
317b8e80941Smrg
318b8e80941Smrg   return VK_SUCCESS;
319b8e80941Smrg}
320b8e80941Smrg
321b8e80941Smrgvoid
322b8e80941Smrgtu_DestroyImageView(VkDevice _device,
323b8e80941Smrg                    VkImageView _iview,
324b8e80941Smrg                    const VkAllocationCallbacks *pAllocator)
325b8e80941Smrg{
326b8e80941Smrg   TU_FROM_HANDLE(tu_device, device, _device);
327b8e80941Smrg   TU_FROM_HANDLE(tu_image_view, iview, _iview);
328b8e80941Smrg
329b8e80941Smrg   if (!iview)
330b8e80941Smrg      return;
331b8e80941Smrg   vk_free2(&device->alloc, pAllocator, iview);
332b8e80941Smrg}
333b8e80941Smrg
334b8e80941Smrgvoid
335b8e80941Smrgtu_buffer_view_init(struct tu_buffer_view *view,
336b8e80941Smrg                    struct tu_device *device,
337b8e80941Smrg                    const VkBufferViewCreateInfo *pCreateInfo)
338b8e80941Smrg{
339b8e80941Smrg   TU_FROM_HANDLE(tu_buffer, buffer, pCreateInfo->buffer);
340b8e80941Smrg
341b8e80941Smrg   view->range = pCreateInfo->range == VK_WHOLE_SIZE
342b8e80941Smrg                    ? buffer->size - pCreateInfo->offset
343b8e80941Smrg                    : pCreateInfo->range;
344b8e80941Smrg   view->vk_format = pCreateInfo->format;
345b8e80941Smrg}
346b8e80941Smrg
347b8e80941SmrgVkResult
348b8e80941Smrgtu_CreateBufferView(VkDevice _device,
349b8e80941Smrg                    const VkBufferViewCreateInfo *pCreateInfo,
350b8e80941Smrg                    const VkAllocationCallbacks *pAllocator,
351b8e80941Smrg                    VkBufferView *pView)
352b8e80941Smrg{
353b8e80941Smrg   TU_FROM_HANDLE(tu_device, device, _device);
354b8e80941Smrg   struct tu_buffer_view *view;
355b8e80941Smrg
356b8e80941Smrg   view = vk_alloc2(&device->alloc, pAllocator, sizeof(*view), 8,
357b8e80941Smrg                    VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
358b8e80941Smrg   if (!view)
359b8e80941Smrg      return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
360b8e80941Smrg
361b8e80941Smrg   tu_buffer_view_init(view, device, pCreateInfo);
362b8e80941Smrg
363b8e80941Smrg   *pView = tu_buffer_view_to_handle(view);
364b8e80941Smrg
365b8e80941Smrg   return VK_SUCCESS;
366b8e80941Smrg}
367b8e80941Smrg
368b8e80941Smrgvoid
369b8e80941Smrgtu_DestroyBufferView(VkDevice _device,
370b8e80941Smrg                     VkBufferView bufferView,
371b8e80941Smrg                     const VkAllocationCallbacks *pAllocator)
372b8e80941Smrg{
373b8e80941Smrg   TU_FROM_HANDLE(tu_device, device, _device);
374b8e80941Smrg   TU_FROM_HANDLE(tu_buffer_view, view, bufferView);
375b8e80941Smrg
376b8e80941Smrg   if (!view)
377b8e80941Smrg      return;
378b8e80941Smrg
379b8e80941Smrg   vk_free2(&device->alloc, pAllocator, view);
380b8e80941Smrg}
381