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 for (uint32_t r = 0; r < range_count; r++) {
46 const uint32_t level_count =
47 vk_image_subresource_level_count(&image->vk, &ranges[r]);
48
49 for (uint32_t l = 0; l < level_count; l++) {
50 const uint32_t level = ranges[r].baseMipLevel + l;
51
52 const VkExtent3D level_extent =
53 vk_image_mip_level_extent(&image->vk, level);
54
55 uint32_t base_array_layer, layer_count;
56 if (image->vk.image_type == VK_IMAGE_TYPE_3D) {
57 base_array_layer = 0;
58 layer_count = level_extent.depth;
59 } else {
60 base_array_layer = ranges[r].baseArrayLayer;
61 layer_count =
62 vk_image_subresource_layer_count(&image->vk, &ranges[r]);
63 }
64
65 const VkImageViewUsageCreateInfo view_usage_info = {
66 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO,
67 .usage = (ranges[r].aspectMask & VK_IMAGE_ASPECT_COLOR_BIT)
68 ? VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
69 : VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
70 };
71 const VkImageViewCreateInfo view_info = {
72 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
73 .flags = VK_IMAGE_VIEW_CREATE_INTERNAL_MESA,
74 .pNext = &view_usage_info,
75 .image = hk_image_to_handle(image),
76 .viewType = render_view_type(image->vk.image_type, layer_count),
77 .format = format,
78 .subresourceRange =
79 {
80 .aspectMask = image->vk.aspects,
81 .baseMipLevel = level,
82 .levelCount = 1,
83 .baseArrayLayer = base_array_layer,
84 .layerCount = layer_count,
85 },
86 };
87
88 /* We use vk_meta_create_image_view here for lifetime managemnt */
89 VkImageView view;
90 result =
91 vk_meta_create_image_view(&cmd->vk, &dev->meta, &view_info, &view);
92 assert(result == VK_SUCCESS);
93
94 VkRenderingInfo render = {
95 .sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
96 .renderArea =
97 {
98 .offset = {0, 0},
99 .extent = {level_extent.width, level_extent.height},
100 },
101 .layerCount = layer_count,
102 };
103
104 VkRenderingAttachmentInfo vk_att = {
105 .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
106 .imageView = view,
107 .imageLayout = image_layout,
108 .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
109 .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
110 .clearValue = *clear_value,
111 };
112
113 if (ranges[r].aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) {
114 render.colorAttachmentCount = 1;
115 render.pColorAttachments = &vk_att;
116 }
117 if (ranges[r].aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT)
118 render.pDepthAttachment = &vk_att;
119 if (ranges[r].aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT)
120 render.pStencilAttachment = &vk_att;
121
122 hk_CmdBeginRendering(hk_cmd_buffer_to_handle(cmd), &render);
123 hk_CmdEndRendering(hk_cmd_buffer_to_handle(cmd));
124 }
125 }
126 }
127
128 static VkFormat
vk_packed_int_format_for_size(unsigned size_B)129 vk_packed_int_format_for_size(unsigned size_B)
130 {
131 switch (size_B) {
132 case 1:
133 return VK_FORMAT_R8_UINT;
134 case 2:
135 return VK_FORMAT_R16_UINT;
136 case 4:
137 return VK_FORMAT_R32_UINT;
138 case 8:
139 return VK_FORMAT_R32G32_UINT;
140 case 16:
141 return VK_FORMAT_R32G32B32A32_UINT;
142 default:
143 unreachable("Invalid image format size");
144 }
145 }
146
147 VKAPI_ATTR void VKAPI_CALL
hk_CmdClearColorImage(VkCommandBuffer commandBuffer,VkImage _image,VkImageLayout imageLayout,const VkClearColorValue * pColor,uint32_t rangeCount,const VkImageSubresourceRange * pRanges)148 hk_CmdClearColorImage(VkCommandBuffer commandBuffer, VkImage _image,
149 VkImageLayout imageLayout,
150 const VkClearColorValue *pColor, uint32_t rangeCount,
151 const VkImageSubresourceRange *pRanges)
152 {
153 VK_FROM_HANDLE(hk_cmd_buffer, cmd, commandBuffer);
154 VK_FROM_HANDLE(hk_image, image, _image);
155
156 VkClearValue clear_value = {
157 .color = *pColor,
158 };
159
160 VkFormat vk_format = image->vk.format;
161 if (vk_format == VK_FORMAT_R64_UINT || vk_format == VK_FORMAT_R64_SINT)
162 vk_format = VK_FORMAT_R32G32_UINT;
163
164 enum pipe_format p_format = vk_format_to_pipe_format(vk_format);
165 assert(p_format != PIPE_FORMAT_NONE);
166
167 if (!ail_pixel_format[p_format].renderable) {
168 memset(&clear_value, 0, sizeof(clear_value));
169 util_format_pack_rgba(p_format, clear_value.color.uint32, pColor->uint32,
170 1);
171
172 unsigned bpp = util_format_get_blocksize(p_format);
173 vk_format = vk_packed_int_format_for_size(bpp);
174 }
175
176 clear_image(cmd, image, imageLayout, vk_format, &clear_value, rangeCount,
177 pRanges);
178 }
179
180 VKAPI_ATTR void VKAPI_CALL
hk_CmdClearDepthStencilImage(VkCommandBuffer commandBuffer,VkImage _image,VkImageLayout imageLayout,const VkClearDepthStencilValue * pDepthStencil,uint32_t rangeCount,const VkImageSubresourceRange * pRanges)181 hk_CmdClearDepthStencilImage(VkCommandBuffer commandBuffer, VkImage _image,
182 VkImageLayout imageLayout,
183 const VkClearDepthStencilValue *pDepthStencil,
184 uint32_t rangeCount,
185 const VkImageSubresourceRange *pRanges)
186 {
187 VK_FROM_HANDLE(hk_cmd_buffer, cmd, commandBuffer);
188 VK_FROM_HANDLE(hk_image, image, _image);
189
190 const VkClearValue clear_value = {
191 .depthStencil = *pDepthStencil,
192 };
193
194 clear_image(cmd, image, imageLayout, image->vk.format, &clear_value,
195 rangeCount, pRanges);
196 }
197