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