• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2024 Valve Corporation
3  * Copyright 2024 Alyssa Rosenzweig
4  * Copyright 2022-2023 Collabora Ltd. and Red Hat Inc.
5  * SPDX-License-Identifier: MIT
6  */
7 #include "hk_cmd_buffer.h"
8 #include "layout.h"
9 
10 #include "hk_device.h"
11 #include "hk_entrypoints.h"
12 #include "hk_image.h"
13 #include "hk_image_view.h"
14 #include "hk_physical_device.h"
15 
16 #include "vk_format.h"
17 #include "vk_meta.h"
18 
19 static VkImageViewType
render_view_type(VkImageType image_type,unsigned layer_count)20 render_view_type(VkImageType image_type, unsigned layer_count)
21 {
22    switch (image_type) {
23    case VK_IMAGE_TYPE_1D:
24       return layer_count == 1 ? VK_IMAGE_VIEW_TYPE_1D
25                               : VK_IMAGE_VIEW_TYPE_1D_ARRAY;
26    case VK_IMAGE_TYPE_2D:
27       return layer_count == 1 ? VK_IMAGE_VIEW_TYPE_2D
28                               : VK_IMAGE_VIEW_TYPE_2D_ARRAY;
29    case VK_IMAGE_TYPE_3D:
30       return VK_IMAGE_VIEW_TYPE_3D;
31    default:
32       unreachable("Invalid image type");
33    }
34 }
35 
36 static void
clear_image(struct hk_cmd_buffer * cmd,struct hk_image * image,VkImageLayout image_layout,VkFormat format,const VkClearValue * clear_value,uint32_t range_count,const VkImageSubresourceRange * ranges)37 clear_image(struct hk_cmd_buffer *cmd, struct hk_image *image,
38             VkImageLayout image_layout, VkFormat format,
39             const VkClearValue *clear_value, uint32_t range_count,
40             const VkImageSubresourceRange *ranges)
41 {
42    struct hk_device *dev = hk_cmd_buffer_device(cmd);
43    ASSERTED VkResult result;
44 
45    /* TODO: Use fast clear */
46    bool compressed = ail_is_compressed(&image->planes[0].layout);
47    perf_debug(dev, "Image clear (%scompressed)", compressed ? "" : "un");
48 
49    for (uint32_t r = 0; r < range_count; r++) {
50       const uint32_t level_count =
51          vk_image_subresource_level_count(&image->vk, &ranges[r]);
52 
53       for (uint32_t l = 0; l < level_count; l++) {
54          const uint32_t level = ranges[r].baseMipLevel + l;
55 
56          const VkExtent3D level_extent =
57             vk_image_mip_level_extent(&image->vk, level);
58 
59          uint32_t base_array_layer, layer_count;
60          if (image->vk.image_type == VK_IMAGE_TYPE_3D) {
61             base_array_layer = 0;
62             layer_count = level_extent.depth;
63          } else {
64             base_array_layer = ranges[r].baseArrayLayer;
65             layer_count =
66                vk_image_subresource_layer_count(&image->vk, &ranges[r]);
67          }
68 
69          const VkImageViewUsageCreateInfo view_usage_info = {
70             .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO,
71             .usage = (ranges[r].aspectMask & VK_IMAGE_ASPECT_COLOR_BIT)
72                         ? VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
73                         : VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
74          };
75          const VkImageViewCreateInfo view_info = {
76             .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
77             .flags = VK_IMAGE_VIEW_CREATE_DRIVER_INTERNAL_BIT_MESA,
78             .pNext = &view_usage_info,
79             .image = hk_image_to_handle(image),
80             .viewType = render_view_type(image->vk.image_type, layer_count),
81             .format = format,
82             .subresourceRange =
83                {
84                   .aspectMask = image->vk.aspects,
85                   .baseMipLevel = level,
86                   .levelCount = 1,
87                   .baseArrayLayer = base_array_layer,
88                   .layerCount = layer_count,
89                },
90          };
91 
92          /* We use vk_meta_create_image_view here for lifetime managemnt */
93          VkImageView view;
94          result =
95             vk_meta_create_image_view(&cmd->vk, &dev->meta, &view_info, &view);
96          assert(result == VK_SUCCESS);
97 
98          VkRenderingInfo render = {
99             .sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
100             .renderArea =
101                {
102                   .offset = {0, 0},
103                   .extent = {level_extent.width, level_extent.height},
104                },
105             .layerCount = layer_count,
106          };
107 
108          VkRenderingAttachmentInfo vk_att = {
109             .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
110             .imageView = view,
111             .imageLayout = image_layout,
112             .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
113             .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
114             .clearValue = *clear_value,
115          };
116 
117          if (ranges[r].aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) {
118             render.colorAttachmentCount = 1;
119             render.pColorAttachments = &vk_att;
120          }
121          if (ranges[r].aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT)
122             render.pDepthAttachment = &vk_att;
123          if (ranges[r].aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT)
124             render.pStencilAttachment = &vk_att;
125 
126          hk_CmdBeginRendering(hk_cmd_buffer_to_handle(cmd), &render);
127          hk_CmdEndRendering(hk_cmd_buffer_to_handle(cmd));
128       }
129    }
130 }
131 
132 static VkFormat
vk_packed_int_format_for_size(unsigned size_B)133 vk_packed_int_format_for_size(unsigned size_B)
134 {
135    switch (size_B) {
136    case 1:
137       return VK_FORMAT_R8_UINT;
138    case 2:
139       return VK_FORMAT_R16_UINT;
140    case 4:
141       return VK_FORMAT_R32_UINT;
142    case 8:
143       return VK_FORMAT_R32G32_UINT;
144    case 16:
145       return VK_FORMAT_R32G32B32A32_UINT;
146    default:
147       unreachable("Invalid image format size");
148    }
149 }
150 
151 VKAPI_ATTR void VKAPI_CALL
hk_CmdClearColorImage(VkCommandBuffer commandBuffer,VkImage _image,VkImageLayout imageLayout,const VkClearColorValue * pColor,uint32_t rangeCount,const VkImageSubresourceRange * pRanges)152 hk_CmdClearColorImage(VkCommandBuffer commandBuffer, VkImage _image,
153                       VkImageLayout imageLayout,
154                       const VkClearColorValue *pColor, uint32_t rangeCount,
155                       const VkImageSubresourceRange *pRanges)
156 {
157    VK_FROM_HANDLE(hk_cmd_buffer, cmd, commandBuffer);
158    VK_FROM_HANDLE(hk_image, image, _image);
159 
160    VkClearValue clear_value = {
161       .color = *pColor,
162    };
163 
164    VkFormat vk_format = image->vk.format;
165    if (vk_format == VK_FORMAT_R64_UINT || vk_format == VK_FORMAT_R64_SINT)
166       vk_format = VK_FORMAT_R32G32_UINT;
167 
168    enum pipe_format p_format = hk_format_to_pipe_format(vk_format);
169    assert(p_format != PIPE_FORMAT_NONE);
170 
171    if (!ail_pixel_format[p_format].renderable) {
172       memset(&clear_value, 0, sizeof(clear_value));
173       util_format_pack_rgba(p_format, clear_value.color.uint32, pColor->uint32,
174                             1);
175 
176       unsigned bpp = util_format_get_blocksize(p_format);
177       vk_format = vk_packed_int_format_for_size(bpp);
178    }
179 
180    clear_image(cmd, image, imageLayout, vk_format, &clear_value, rangeCount,
181                pRanges);
182 }
183 
184 VKAPI_ATTR void VKAPI_CALL
hk_CmdClearDepthStencilImage(VkCommandBuffer commandBuffer,VkImage _image,VkImageLayout imageLayout,const VkClearDepthStencilValue * pDepthStencil,uint32_t rangeCount,const VkImageSubresourceRange * pRanges)185 hk_CmdClearDepthStencilImage(VkCommandBuffer commandBuffer, VkImage _image,
186                              VkImageLayout imageLayout,
187                              const VkClearDepthStencilValue *pDepthStencil,
188                              uint32_t rangeCount,
189                              const VkImageSubresourceRange *pRanges)
190 {
191    VK_FROM_HANDLE(hk_cmd_buffer, cmd, commandBuffer);
192    VK_FROM_HANDLE(hk_image, image, _image);
193 
194    const VkClearValue clear_value = {
195       .depthStencil = *pDepthStencil,
196    };
197 
198    clear_image(cmd, image, imageLayout, image->vk.format, &clear_value,
199                rangeCount, pRanges);
200 }
201