xref: /aosp_15_r20/external/mesa3d/src/panfrost/vulkan/panvk_vX_image_view.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2021 Collabora Ltd.
3  *
4  * Derived from tu_image.c which is:
5  * Copyright © 2016 Red Hat.
6  * Copyright © 2016 Bas Nieuwenhuizen
7  * Copyright © 2015 Intel Corporation
8  *
9  * SPDX-License-Identifier: MIT
10  */
11 
12 #include "vk_format.h"
13 #include "vk_log.h"
14 
15 #include "panvk_device.h"
16 #include "panvk_entrypoints.h"
17 #include "panvk_image.h"
18 #include "panvk_image_view.h"
19 #include "panvk_priv_bo.h"
20 
21 #include "genxml/gen_macros.h"
22 
23 static enum mali_texture_dimension
panvk_view_type_to_mali_tex_dim(VkImageViewType type)24 panvk_view_type_to_mali_tex_dim(VkImageViewType type)
25 {
26    switch (type) {
27    case VK_IMAGE_VIEW_TYPE_1D:
28    case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
29       return MALI_TEXTURE_DIMENSION_1D;
30    case VK_IMAGE_VIEW_TYPE_2D:
31    case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
32       return MALI_TEXTURE_DIMENSION_2D;
33    case VK_IMAGE_VIEW_TYPE_3D:
34       return MALI_TEXTURE_DIMENSION_3D;
35    case VK_IMAGE_VIEW_TYPE_CUBE:
36    case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
37       return MALI_TEXTURE_DIMENSION_CUBE;
38    default:
39       unreachable("Invalid view type");
40    }
41 }
42 
43 static void
panvk_convert_swizzle(const VkComponentMapping * in,unsigned char * out)44 panvk_convert_swizzle(const VkComponentMapping *in, unsigned char *out)
45 {
46    const VkComponentSwizzle *comp = &in->r;
47    for (unsigned i = 0; i < 4; i++) {
48       switch (comp[i]) {
49       case VK_COMPONENT_SWIZZLE_ZERO:
50          out[i] = PIPE_SWIZZLE_0;
51          break;
52       case VK_COMPONENT_SWIZZLE_ONE:
53          out[i] = PIPE_SWIZZLE_1;
54          break;
55       case VK_COMPONENT_SWIZZLE_R:
56          out[i] = PIPE_SWIZZLE_X;
57          break;
58       case VK_COMPONENT_SWIZZLE_G:
59          out[i] = PIPE_SWIZZLE_Y;
60          break;
61       case VK_COMPONENT_SWIZZLE_B:
62          out[i] = PIPE_SWIZZLE_Z;
63          break;
64       case VK_COMPONENT_SWIZZLE_A:
65          out[i] = PIPE_SWIZZLE_W;
66          break;
67       default:
68          unreachable("Invalid swizzle");
69       }
70    }
71 }
72 
73 VKAPI_ATTR VkResult VKAPI_CALL
panvk_per_arch(CreateImageView)74 panvk_per_arch(CreateImageView)(VkDevice _device,
75                                 const VkImageViewCreateInfo *pCreateInfo,
76                                 const VkAllocationCallbacks *pAllocator,
77                                 VkImageView *pView)
78 {
79    VK_FROM_HANDLE(panvk_device, device, _device);
80    VK_FROM_HANDLE(panvk_image, image, pCreateInfo->image);
81    bool driver_internal =
82       (pCreateInfo->flags & VK_IMAGE_VIEW_CREATE_DRIVER_INTERNAL_BIT_MESA) != 0;
83    struct panvk_image_view *view;
84 
85    view = vk_image_view_create(&device->vk, driver_internal, pCreateInfo,
86                                pAllocator, sizeof(*view));
87    if (view == NULL)
88       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
89 
90    view->pview = (struct pan_image_view){
91       .planes[0] = &image->pimage,
92       .format = vk_format_to_pipe_format(view->vk.view_format),
93       .dim = panvk_view_type_to_mali_tex_dim(view->vk.view_type),
94       .nr_samples = image->pimage.layout.nr_samples,
95       .first_level = view->vk.base_mip_level,
96       .last_level = view->vk.base_mip_level + view->vk.level_count - 1,
97       .first_layer = view->vk.base_array_layer,
98       .last_layer = view->vk.base_array_layer + view->vk.layer_count - 1,
99    };
100    panvk_convert_swizzle(&view->vk.swizzle, view->pview.swizzle);
101 
102    /* We need to patch the view format when the image contains both
103     * depth and stencil but the view only contains one of these components, so
104     * we can ignore the component we don't use.
105     */
106    if (vk_format_is_depth_or_stencil(view->vk.view_format)) {
107       if (image->vk.format == VK_FORMAT_D32_SFLOAT_S8_UINT &&
108           view->vk.view_format != VK_FORMAT_D32_SFLOAT_S8_UINT)
109          view->pview.format = view->vk.view_format == VK_FORMAT_D32_SFLOAT
110                                  ? PIPE_FORMAT_Z32_FLOAT_S8X24_UINT
111                                  : PIPE_FORMAT_X32_S8X24_UINT;
112 
113       if (image->vk.format == VK_FORMAT_D24_UNORM_S8_UINT &&
114           view->vk.view_format == VK_FORMAT_S8_UINT)
115          view->pview.format = PIPE_FORMAT_X24S8_UINT;
116 
117       if (image->vk.format == VK_FORMAT_D32_SFLOAT_S8_UINT &&
118           view->vk.view_format == VK_FORMAT_S8_UINT)
119          view->pview.format = PIPE_FORMAT_X32_S8X24_UINT;
120    }
121 
122    VkImageUsageFlags tex_usage_mask =
123       VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
124 
125 #if PAN_ARCH >= 9
126    /* Valhall passes a texture descriptor to LEA_TEX. */
127    tex_usage_mask |= VK_IMAGE_USAGE_STORAGE_BIT;
128 #endif
129 
130    if (view->vk.usage & tex_usage_mask) {
131       /* Use a temporary pan_image_view so we can tweak it for texture
132        * descriptor emission without changing the original definition.
133        */
134       struct pan_image_view pview = view->pview;
135 
136       if (util_format_is_depth_or_stencil(view->pview.format)) {
137          /* Vulkan wants R001, where the depth/stencil is stored in the red
138           * component, but the pan_format/texture logic gives us RRRR.
139           * Tweak the swizzle so we get what Vulkan wants.
140           */
141          static const unsigned char r001[4] = {
142             PIPE_SWIZZLE_X,
143             PIPE_SWIZZLE_0,
144             PIPE_SWIZZLE_0,
145             PIPE_SWIZZLE_1,
146          };
147 
148          util_format_compose_swizzles(r001, view->pview.swizzle, pview.swizzle);
149       }
150 
151       struct panvk_pool_alloc_info alloc_info = {
152          .alignment = pan_alignment(TEXTURE),
153          .size = GENX(panfrost_estimate_texture_payload_size)(&pview),
154       };
155 
156       view->mem = panvk_pool_alloc_mem(&device->mempools.rw, alloc_info);
157 
158       struct panfrost_ptr ptr = {
159          .gpu = panvk_priv_mem_dev_addr(view->mem),
160          .cpu = panvk_priv_mem_host_addr(view->mem),
161       };
162 
163       GENX(panfrost_new_texture)(&pview, view->descs.tex.opaque, &ptr);
164    }
165 
166 #if PAN_ARCH <= 7
167    if (view->vk.usage & VK_IMAGE_USAGE_STORAGE_BIT) {
168       bool is_3d = image->pimage.layout.dim == MALI_TEXTURE_DIMENSION_3D;
169       unsigned offset = image->pimage.data.offset;
170       offset +=
171          panfrost_texture_offset(&image->pimage.layout, view->pview.first_level,
172                                  is_3d ? 0 : view->pview.first_layer,
173                                  is_3d ? view->pview.first_layer : 0);
174 
175       pan_pack(view->descs.img_attrib_buf[0].opaque, ATTRIBUTE_BUFFER, cfg) {
176          /* The format is the only thing we lack to emit attribute descriptors
177           * when copying from the set to the attribute tables. Instead of
178           * making the descriptor size to store an extra format, we pack
179           * the 22-bit format with the texel stride, which is expected to be
180           * fit in remaining 10 bits.
181           */
182          uint32_t fmt_blksize = util_format_get_blocksize(view->pview.format);
183          uint32_t hw_fmt =
184             GENX(panfrost_format_from_pipe_format)(view->pview.format)->hw;
185 
186          assert(fmt_blksize < BITFIELD_MASK(10));
187          assert(hw_fmt < BITFIELD_MASK(22));
188 
189          cfg.type = image->pimage.layout.modifier == DRM_FORMAT_MOD_LINEAR
190                        ? MALI_ATTRIBUTE_TYPE_3D_LINEAR
191                        : MALI_ATTRIBUTE_TYPE_3D_INTERLEAVED;
192          cfg.pointer = image->pimage.data.base + offset;
193          cfg.stride = fmt_blksize | (hw_fmt << 10);
194          cfg.size = pan_kmod_bo_size(image->bo) - offset;
195       }
196 
197       pan_pack(view->descs.img_attrib_buf[1].opaque,
198                ATTRIBUTE_BUFFER_CONTINUATION_3D, cfg) {
199          unsigned level = view->pview.first_level;
200          VkExtent3D extent = view->vk.extent;
201 
202          cfg.s_dimension = extent.width;
203          cfg.t_dimension = extent.height;
204          cfg.r_dimension =
205             view->pview.dim == MALI_TEXTURE_DIMENSION_3D
206                ? extent.depth
207                : (view->pview.last_layer - view->pview.first_layer + 1);
208          cfg.row_stride = image->pimage.layout.slices[level].row_stride;
209          if (cfg.r_dimension > 1) {
210             cfg.slice_stride =
211                panfrost_get_layer_stride(&image->pimage.layout, level);
212          }
213       }
214    }
215 #endif
216 
217    *pView = panvk_image_view_to_handle(view);
218    return VK_SUCCESS;
219 }
220 
221 VKAPI_ATTR void VKAPI_CALL
panvk_per_arch(DestroyImageView)222 panvk_per_arch(DestroyImageView)(VkDevice _device, VkImageView _view,
223                                  const VkAllocationCallbacks *pAllocator)
224 {
225    VK_FROM_HANDLE(panvk_device, device, _device);
226    VK_FROM_HANDLE(panvk_image_view, view, _view);
227 
228    if (!view)
229       return;
230 
231    panvk_pool_free_mem(&device->mempools.rw, view->mem);
232    vk_image_view_destroy(&device->vk, pAllocator, &view->vk);
233 }
234