• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2022 Collabora Ltd. and Red Hat Inc.
3  * SPDX-License-Identifier: MIT
4  */
5 #include "nvk_image_view.h"
6 
7 #include "nvk_device.h"
8 #include "nvk_entrypoints.h"
9 #include "nvk_format.h"
10 #include "nvk_image.h"
11 #include "nvk_physical_device.h"
12 
13 #include "vk_format.h"
14 
15 static enum nil_view_type
vk_image_view_type_to_nil_view_type(VkImageViewType view_type)16 vk_image_view_type_to_nil_view_type(VkImageViewType view_type)
17 {
18    switch (view_type) {
19    case VK_IMAGE_VIEW_TYPE_1D:         return NIL_VIEW_TYPE_1D;
20    case VK_IMAGE_VIEW_TYPE_2D:         return NIL_VIEW_TYPE_2D;
21    case VK_IMAGE_VIEW_TYPE_3D:         return NIL_VIEW_TYPE_3D;
22    case VK_IMAGE_VIEW_TYPE_CUBE:       return NIL_VIEW_TYPE_CUBE;
23    case VK_IMAGE_VIEW_TYPE_1D_ARRAY:   return NIL_VIEW_TYPE_1D_ARRAY;
24    case VK_IMAGE_VIEW_TYPE_2D_ARRAY:   return NIL_VIEW_TYPE_2D_ARRAY;
25    case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: return NIL_VIEW_TYPE_CUBE_ARRAY;
26    default:
27       unreachable("Invalid image view type");
28    }
29 }
30 
31 static enum pipe_swizzle
vk_swizzle_to_pipe(VkComponentSwizzle swizzle)32 vk_swizzle_to_pipe(VkComponentSwizzle swizzle)
33 {
34    switch (swizzle) {
35    case VK_COMPONENT_SWIZZLE_R:     return PIPE_SWIZZLE_X;
36    case VK_COMPONENT_SWIZZLE_G:     return PIPE_SWIZZLE_Y;
37    case VK_COMPONENT_SWIZZLE_B:     return PIPE_SWIZZLE_Z;
38    case VK_COMPONENT_SWIZZLE_A:     return PIPE_SWIZZLE_W;
39    case VK_COMPONENT_SWIZZLE_ONE:   return PIPE_SWIZZLE_1;
40    case VK_COMPONENT_SWIZZLE_ZERO:  return PIPE_SWIZZLE_0;
41    default:
42       unreachable("Invalid component swizzle");
43    }
44 }
45 
46 static void
image_uncompressed_view(struct nil_image * image,struct nil_view * view,uint64_t * base_addr)47 image_uncompressed_view(struct nil_image *image,
48                         struct nil_view *view,
49                         uint64_t *base_addr)
50 {
51    assert(view->num_levels == 1);
52 
53    uint64_t offset_B;
54    nil_image_level_as_uncompressed(image, view->base_level, image, &offset_B);
55    *base_addr += offset_B;
56    view->base_level = 0;
57 }
58 
59 static void
image_3d_view_as_2d_array(struct nil_image * image,struct nil_view * view,uint64_t * base_addr)60 image_3d_view_as_2d_array(struct nil_image *image,
61                           struct nil_view *view,
62                           uint64_t *base_addr)
63 {
64    assert(view->type == NIL_VIEW_TYPE_2D ||
65           view->type == NIL_VIEW_TYPE_2D_ARRAY);
66    assert(view->num_levels == 1);
67 
68    uint64_t offset_B;
69    nil_image_3d_level_as_2d_array(image, view->base_level, image, &offset_B);
70    *base_addr += offset_B;
71    view->base_level = 0;
72 }
73 
74 static enum pipe_format
get_stencil_format(enum pipe_format format)75 get_stencil_format(enum pipe_format format)
76 {
77    switch (format) {
78    case PIPE_FORMAT_S8_UINT:              return PIPE_FORMAT_S8_UINT;
79    case PIPE_FORMAT_Z24_UNORM_S8_UINT:    return PIPE_FORMAT_X24S8_UINT;
80    case PIPE_FORMAT_S8_UINT_Z24_UNORM:    return PIPE_FORMAT_S8X24_UINT;
81    case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT: return PIPE_FORMAT_X32_S8X24_UINT;
82    default: unreachable("Unsupported depth/stencil format");
83    }
84 }
85 
86 VkResult
nvk_image_view_init(struct nvk_device * dev,struct nvk_image_view * view,bool driver_internal,const VkImageViewCreateInfo * pCreateInfo)87 nvk_image_view_init(struct nvk_device *dev,
88                     struct nvk_image_view *view,
89                     bool driver_internal,
90                     const VkImageViewCreateInfo *pCreateInfo)
91 {
92    VK_FROM_HANDLE(nvk_image, image, pCreateInfo->image);
93    VkResult result;
94 
95    memset(view, 0, sizeof(*view));
96 
97    vk_image_view_init(&dev->vk, &view->vk, driver_internal, pCreateInfo);
98 
99    /* First, figure out which image planes we need.
100     * For depth/stencil, we only have plane so simply assert
101     * and then map directly betweeen the image and view plane
102     */
103    if (image->vk.aspects & (VK_IMAGE_ASPECT_DEPTH_BIT |
104                             VK_IMAGE_ASPECT_STENCIL_BIT)) {
105       assert(image->plane_count == 1);
106       assert(nvk_image_aspects_to_plane(image, view->vk.aspects) == 0);
107       view->plane_count = 1;
108       view->planes[0].image_plane = 0;
109    } else {
110       /* For other formats, retrieve the plane count from the aspect mask
111        * and then walk through the aspect mask to map each image plane
112        * to its corresponding view plane
113        */
114       assert(util_bitcount(view->vk.aspects) ==
115              vk_format_get_plane_count(view->vk.format));
116       view->plane_count = 0;
117       u_foreach_bit(aspect_bit, view->vk.aspects) {
118          uint8_t image_plane = nvk_image_aspects_to_plane(image, 1u << aspect_bit);
119          view->planes[view->plane_count++].image_plane = image_plane;
120       }
121    }
122 
123    /* Finally, fill in each view plane separately */
124    for (unsigned view_plane = 0; view_plane < view->plane_count; view_plane++) {
125       const uint8_t image_plane = view->planes[view_plane].image_plane;
126       struct nil_image nil_image = image->planes[image_plane].nil;
127       uint64_t base_addr = nvk_image_base_address(image, image_plane);
128 
129       const struct vk_format_ycbcr_info *ycbcr_info =
130          vk_format_get_ycbcr_info(view->vk.format);
131       assert(ycbcr_info || view_plane == 0);
132       VkFormat plane_format = ycbcr_info ?
133          ycbcr_info->planes[view_plane].format : view->vk.format;
134       enum pipe_format p_format = vk_format_to_pipe_format(plane_format);
135       if (view->vk.aspects == VK_IMAGE_ASPECT_STENCIL_BIT)
136          p_format = get_stencil_format(p_format);
137 
138       struct nil_view nil_view = {
139          .type = vk_image_view_type_to_nil_view_type(view->vk.view_type),
140          .format = p_format,
141          .base_level = view->vk.base_mip_level,
142          .num_levels = view->vk.level_count,
143          .base_array_layer = view->vk.base_array_layer,
144          .array_len = view->vk.layer_count,
145          .swizzle = {
146             vk_swizzle_to_pipe(view->vk.swizzle.r),
147             vk_swizzle_to_pipe(view->vk.swizzle.g),
148             vk_swizzle_to_pipe(view->vk.swizzle.b),
149             vk_swizzle_to_pipe(view->vk.swizzle.a),
150          },
151          .min_lod_clamp = view->vk.min_lod,
152       };
153 
154       if (util_format_is_compressed(nil_image.format) &&
155          !util_format_is_compressed(nil_view.format))
156          image_uncompressed_view(&nil_image, &nil_view, &base_addr);
157 
158       if (nil_image.dim == NIL_IMAGE_DIM_3D &&
159          nil_view.type != NIL_VIEW_TYPE_3D)
160          image_3d_view_as_2d_array(&nil_image, &nil_view, &base_addr);
161 
162       if (view->vk.usage & (VK_IMAGE_USAGE_SAMPLED_BIT |
163                            VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) {
164          uint32_t tic[8];
165          nil_image_fill_tic(&nvk_device_physical(dev)->info,
166                            &nil_image, &nil_view, base_addr, tic);
167 
168          result = nvk_descriptor_table_add(dev, &dev->images, tic, sizeof(tic),
169                                           &view->planes[view_plane].sampled_desc_index);
170          if (result != VK_SUCCESS) {
171             nvk_image_view_finish(dev, view);
172             return result;
173          }
174       }
175 
176       if (view->vk.usage & VK_IMAGE_USAGE_STORAGE_BIT) {
177          /* For storage images, we can't have any cubes */
178          if (view->vk.view_type == VK_IMAGE_VIEW_TYPE_CUBE ||
179             view->vk.view_type == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
180             nil_view.type = NIL_VIEW_TYPE_2D_ARRAY;
181 
182          if (view->vk.view_type == VK_IMAGE_VIEW_TYPE_3D) {
183             /* Without VK_AMD_shader_image_load_store_lod, the client can only
184              * get at the first LOD from the shader anyway.
185              */
186             assert(view->vk.base_array_layer == 0);
187             assert(view->vk.layer_count == 1);
188             nil_view.type = NIL_VIEW_TYPE_2D_ARRAY;
189             nil_view.num_levels = 1;
190             nil_view.base_array_layer = view->vk.storage.z_slice_offset;
191             nil_view.array_len = view->vk.storage.z_slice_count;
192             image_3d_view_as_2d_array(&nil_image, &nil_view, &base_addr);
193          }
194 
195          uint32_t tic[8];
196          nil_image_fill_tic(&nvk_device_physical(dev)->info,
197                            &nil_image, &nil_view, base_addr, tic);
198 
199          result = nvk_descriptor_table_add(dev, &dev->images, tic, sizeof(tic),
200                                           &view->planes[view_plane].storage_desc_index);
201          if (result != VK_SUCCESS) {
202             nvk_image_view_finish(dev, view);
203             return result;
204          }
205       }
206    }
207 
208    return VK_SUCCESS;
209 }
210 
211 void
nvk_image_view_finish(struct nvk_device * dev,struct nvk_image_view * view)212 nvk_image_view_finish(struct nvk_device *dev,
213                       struct nvk_image_view *view)
214 {
215    for (uint8_t plane = 0; plane < view->plane_count; plane++) {
216       if (view->planes[plane].sampled_desc_index) {
217       nvk_descriptor_table_remove(dev, &dev->images,
218                                   view->planes[plane].sampled_desc_index);
219       }
220 
221       if (view->planes[plane].storage_desc_index) {
222          nvk_descriptor_table_remove(dev, &dev->images,
223                                     view->planes[plane].storage_desc_index);
224       }
225    }
226 
227    vk_image_view_finish(&view->vk);
228 }
229 
230 VKAPI_ATTR VkResult VKAPI_CALL
nvk_CreateImageView(VkDevice _device,const VkImageViewCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkImageView * pView)231 nvk_CreateImageView(VkDevice _device,
232                     const VkImageViewCreateInfo *pCreateInfo,
233                     const VkAllocationCallbacks *pAllocator,
234                     VkImageView *pView)
235 {
236    VK_FROM_HANDLE(nvk_device, dev, _device);
237    struct nvk_image_view *view;
238    VkResult result;
239 
240    view = vk_alloc2(&dev->vk.alloc, pAllocator, sizeof(*view), 8,
241                     VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
242    if (!view)
243       return vk_error(dev, VK_ERROR_OUT_OF_HOST_MEMORY);
244 
245    result = nvk_image_view_init(dev, view, false, pCreateInfo);
246    if (result != VK_SUCCESS) {
247       vk_free2(&dev->vk.alloc, pAllocator, view);
248       return result;
249    }
250 
251    *pView = nvk_image_view_to_handle(view);
252 
253    return VK_SUCCESS;
254 }
255 
256 VKAPI_ATTR void VKAPI_CALL
nvk_DestroyImageView(VkDevice _device,VkImageView imageView,const VkAllocationCallbacks * pAllocator)257 nvk_DestroyImageView(VkDevice _device,
258                      VkImageView imageView,
259                      const VkAllocationCallbacks *pAllocator)
260 {
261    VK_FROM_HANDLE(nvk_device, dev, _device);
262    VK_FROM_HANDLE(nvk_image_view, view, imageView);
263 
264    if (!view)
265       return;
266 
267    nvk_image_view_finish(dev, view);
268    vk_free2(&dev->vk.alloc, pAllocator, view);
269 }
270