1 /*
2 * Copyright © 2022 Collabora Ltd. and Red Hat Inc.
3 * SPDX-License-Identifier: MIT
4 */
5 #include "nvk_cmd_buffer.h"
6
7 #include "nvk_device.h"
8 #include "nvk_entrypoints.h"
9 #include "nvk_image.h"
10 #include "nvk_image_view.h"
11 #include "nvk_mme.h"
12 #include "nvk_physical_device.h"
13
14 #include "nil_format.h"
15 #include "vk_format.h"
16
17 #include "nvk_cl9097.h"
18 #include "drf.h"
19
20 void
nvk_mme_clear(struct mme_builder * b)21 nvk_mme_clear(struct mme_builder *b)
22 {
23 struct mme_value payload = mme_load(b);
24 struct mme_value view_mask = nvk_mme_load_scratch(b, VIEW_MASK);
25
26 const uint32_t arr_idx = 1 << DRF_LO(NV9097_CLEAR_SURFACE_RT_ARRAY_INDEX);
27
28 mme_if(b, ine, view_mask, mme_zero()) {
29 struct mme_value bit = mme_mov(b, mme_imm(1));
30
31 mme_loop(b, mme_imm(32)) {
32 mme_if(b, ine, mme_and(b, view_mask, bit), mme_zero()) {
33 mme_mthd(b, NV9097_CLEAR_SURFACE);
34 mme_emit(b, payload);
35 }
36
37 mme_add_to(b, payload, payload, mme_imm(arr_idx));
38 mme_sll_to(b, bit, bit, mme_imm(1));
39 }
40 mme_free_reg(b, bit);
41 }
42
43 mme_if(b, ieq, view_mask, mme_zero()) {
44 struct mme_value layer_count = mme_load(b);
45
46 mme_loop(b, layer_count) {
47 mme_mthd(b, NV9097_CLEAR_SURFACE);
48 mme_emit(b, payload);
49
50 mme_add_to(b, payload, payload, mme_imm(arr_idx));
51 }
52 mme_free_reg(b, layer_count);
53 }
54
55 mme_free_reg(b, payload);
56 mme_free_reg(b, view_mask);
57 }
58
59 static void
emit_clear_rects(struct nvk_cmd_buffer * cmd,int color_att,bool clear_depth,bool clear_stencil,uint32_t rect_count,const VkClearRect * rects)60 emit_clear_rects(struct nvk_cmd_buffer *cmd,
61 int color_att,
62 bool clear_depth,
63 bool clear_stencil,
64 uint32_t rect_count,
65 const VkClearRect *rects)
66 {
67 struct nvk_rendering_state *render = &cmd->state.gfx.render;
68
69 struct nv_push *p = nvk_cmd_buffer_push(cmd, rect_count * 6);
70
71 for (uint32_t r = 0; r < rect_count; r++) {
72 P_MTHD(p, NV9097, SET_CLEAR_RECT_HORIZONTAL);
73 P_NV9097_SET_CLEAR_RECT_HORIZONTAL(p, {
74 .xmin = rects[r].rect.offset.x,
75 .xmax = rects[r].rect.offset.x + rects[r].rect.extent.width,
76 });
77 P_NV9097_SET_CLEAR_RECT_VERTICAL(p, {
78 .ymin = rects[r].rect.offset.y,
79 .ymax = rects[r].rect.offset.y + rects[r].rect.extent.height,
80 });
81
82 uint32_t payload;
83 V_NV9097_CLEAR_SURFACE(payload, {
84 .z_enable = clear_depth,
85 .stencil_enable = clear_stencil,
86 .r_enable = color_att >= 0,
87 .g_enable = color_att >= 0,
88 .b_enable = color_att >= 0,
89 .a_enable = color_att >= 0,
90 .mrt_select = color_att >= 0 ? color_att : 0,
91 .rt_array_index = rects[r].baseArrayLayer,
92 });
93
94 P_1INC(p, NV9097, CALL_MME_MACRO(NVK_MME_CLEAR));
95 P_INLINE_DATA(p, payload);
96 if (render->view_mask == 0) {
97 P_INLINE_DATA(p, rects[r].layerCount);
98 }
99 }
100 }
101
102 VKAPI_ATTR void VKAPI_CALL
nvk_CmdClearAttachments(VkCommandBuffer commandBuffer,uint32_t attachmentCount,const VkClearAttachment * pAttachments,uint32_t rectCount,const VkClearRect * pRects)103 nvk_CmdClearAttachments(VkCommandBuffer commandBuffer,
104 uint32_t attachmentCount,
105 const VkClearAttachment *pAttachments,
106 uint32_t rectCount,
107 const VkClearRect *pRects)
108 {
109 VK_FROM_HANDLE(nvk_cmd_buffer, cmd, commandBuffer);
110 struct nv_push *p = nvk_cmd_buffer_push(cmd, 2 + attachmentCount * 4);
111
112 P_IMMD(p, NV9097, SET_CLEAR_SURFACE_CONTROL, {
113 .respect_stencil_mask = RESPECT_STENCIL_MASK_FALSE,
114 .use_clear_rect = USE_CLEAR_RECT_TRUE,
115 .use_scissor0 = USE_SCISSOR0_FALSE,
116 .use_viewport_clip0 = USE_VIEWPORT_CLIP0_FALSE,
117 });
118
119 bool clear_depth = false, clear_stencil = false;
120 for (uint32_t i = 0; i < attachmentCount; i++) {
121 if (pAttachments[i].aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) {
122 P_IMMD(p, NV9097, SET_Z_CLEAR_VALUE,
123 fui(pAttachments[i].clearValue.depthStencil.depth));
124 clear_depth = true;
125 }
126
127 if (pAttachments[i].aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) {
128 P_IMMD(p, NV9097, SET_STENCIL_CLEAR_VALUE,
129 pAttachments[i].clearValue.depthStencil.stencil & 0xff);
130 clear_stencil = true;
131 }
132 }
133
134 for (uint32_t i = 0; i < attachmentCount; i++) {
135 if (pAttachments[i].aspectMask != VK_IMAGE_ASPECT_COLOR_BIT)
136 continue;
137
138 if (pAttachments[i].colorAttachment == VK_ATTACHMENT_UNUSED)
139 continue;
140
141 VkClearColorValue color = pAttachments[i].clearValue.color;
142 p = nvk_cmd_buffer_push(cmd, 5);
143
144 P_MTHD(p, NV9097, SET_COLOR_CLEAR_VALUE(0));
145 P_NV9097_SET_COLOR_CLEAR_VALUE(p, 0, color.uint32[0]);
146 P_NV9097_SET_COLOR_CLEAR_VALUE(p, 1, color.uint32[1]);
147 P_NV9097_SET_COLOR_CLEAR_VALUE(p, 2, color.uint32[2]);
148 P_NV9097_SET_COLOR_CLEAR_VALUE(p, 3, color.uint32[3]);
149
150 emit_clear_rects(cmd, pAttachments[i].colorAttachment,
151 clear_depth, clear_stencil, rectCount, pRects);
152
153 /* We only need to clear depth/stencil once */
154 clear_depth = clear_stencil = false;
155 }
156
157 /* No color clears */
158 if (clear_depth || clear_stencil)
159 emit_clear_rects(cmd, -1, clear_depth, clear_stencil, rectCount, pRects);
160 }
161
162 static VkImageViewType
render_view_type(VkImageType image_type,unsigned layer_count)163 render_view_type(VkImageType image_type, unsigned layer_count)
164 {
165 switch (image_type) {
166 case VK_IMAGE_TYPE_1D:
167 return layer_count == 1 ? VK_IMAGE_VIEW_TYPE_1D :
168 VK_IMAGE_VIEW_TYPE_1D_ARRAY;
169 case VK_IMAGE_TYPE_2D:
170 return layer_count == 1 ? VK_IMAGE_VIEW_TYPE_2D :
171 VK_IMAGE_VIEW_TYPE_2D_ARRAY;
172 case VK_IMAGE_TYPE_3D:
173 return VK_IMAGE_VIEW_TYPE_3D;
174 default:
175 unreachable("Invalid image type");
176 }
177 }
178
179 static void
clear_image(struct nvk_cmd_buffer * cmd,struct nvk_image * image,VkImageLayout image_layout,VkFormat format,const VkClearValue * clear_value,uint32_t range_count,const VkImageSubresourceRange * ranges)180 clear_image(struct nvk_cmd_buffer *cmd,
181 struct nvk_image *image,
182 VkImageLayout image_layout,
183 VkFormat format,
184 const VkClearValue *clear_value,
185 uint32_t range_count,
186 const VkImageSubresourceRange *ranges)
187 {
188 struct nvk_device *dev = nvk_cmd_buffer_device(cmd);
189 ASSERTED VkResult result;
190
191 for (uint32_t r = 0; r < range_count; r++) {
192 const uint32_t level_count =
193 vk_image_subresource_level_count(&image->vk, &ranges[r]);
194
195 for (uint32_t l = 0; l < level_count; l++) {
196 const uint32_t level = ranges[r].baseMipLevel + l;
197
198 const VkExtent3D level_extent =
199 vk_image_mip_level_extent(&image->vk, level);
200
201 uint32_t base_array_layer, layer_count;
202 if (image->vk.image_type == VK_IMAGE_TYPE_3D) {
203 base_array_layer = 0;
204 layer_count = level_extent.depth;
205 } else {
206 base_array_layer = ranges[r].baseArrayLayer;
207 layer_count = vk_image_subresource_layer_count(&image->vk,
208 &ranges[r]);
209 }
210
211 const VkImageViewUsageCreateInfo view_usage_info = {
212 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO,
213 .usage = (ranges[r].aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) ?
214 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT :
215 VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
216 };
217 const VkImageViewCreateInfo view_info = {
218 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
219 .pNext = &view_usage_info,
220 .image = nvk_image_to_handle(image),
221 .viewType = render_view_type(image->vk.image_type, layer_count),
222 .format = format,
223 .subresourceRange = {
224 .aspectMask = image->vk.aspects,
225 .baseMipLevel = level,
226 .levelCount = 1,
227 .baseArrayLayer = base_array_layer,
228 .layerCount = layer_count,
229 },
230 };
231
232 struct nvk_image_view view;
233 result = nvk_image_view_init(dev, &view, true, &view_info);
234 assert(result == VK_SUCCESS);
235
236 VkRenderingInfo render = {
237 .sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
238 .renderArea = {
239 .offset = { 0, 0 },
240 .extent = { level_extent.width, level_extent.height },
241 },
242 .layerCount = layer_count,
243 };
244
245 VkRenderingAttachmentInfo vk_att = {
246 .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
247 .imageView = nvk_image_view_to_handle(&view),
248 .imageLayout = image_layout,
249 .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
250 .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
251 .clearValue = *clear_value,
252 };
253
254 if (ranges[r].aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) {
255 render.colorAttachmentCount = 1;
256 render.pColorAttachments = &vk_att;
257 }
258 if (ranges[r].aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT)
259 render.pDepthAttachment = &vk_att;
260 if (ranges[r].aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT)
261 render.pStencilAttachment = &vk_att;
262
263 nvk_CmdBeginRendering(nvk_cmd_buffer_to_handle(cmd), &render);
264 nvk_CmdEndRendering(nvk_cmd_buffer_to_handle(cmd));
265
266 nvk_image_view_finish(dev, &view);
267 }
268 }
269 }
270
271 static VkFormat
vk_packed_int_format_for_size(unsigned size_B)272 vk_packed_int_format_for_size(unsigned size_B)
273 {
274 switch (size_B) {
275 case 1: return VK_FORMAT_R8_UINT;
276 case 2: return VK_FORMAT_R16_UINT;
277 case 4: return VK_FORMAT_R32_UINT;
278 case 8: return VK_FORMAT_R32G32_UINT;
279 case 16: return VK_FORMAT_R32G32B32A32_UINT;
280 default: unreachable("Invalid image format size");
281 }
282 }
283
284 VKAPI_ATTR void VKAPI_CALL
nvk_CmdClearColorImage(VkCommandBuffer commandBuffer,VkImage _image,VkImageLayout imageLayout,const VkClearColorValue * pColor,uint32_t rangeCount,const VkImageSubresourceRange * pRanges)285 nvk_CmdClearColorImage(VkCommandBuffer commandBuffer,
286 VkImage _image,
287 VkImageLayout imageLayout,
288 const VkClearColorValue *pColor,
289 uint32_t rangeCount,
290 const VkImageSubresourceRange *pRanges)
291 {
292 VK_FROM_HANDLE(nvk_cmd_buffer, cmd, commandBuffer);
293 struct nvk_device *dev = nvk_cmd_buffer_device(cmd);
294 VK_FROM_HANDLE(nvk_image, image, _image);
295
296 VkClearValue clear_value = {
297 .color = *pColor,
298 };
299
300 VkFormat vk_format = image->vk.format;
301 if (vk_format == VK_FORMAT_R64_UINT || vk_format == VK_FORMAT_R64_SINT)
302 vk_format = VK_FORMAT_R32G32_UINT;
303
304 enum pipe_format p_format = vk_format_to_pipe_format(vk_format);
305 assert(p_format != PIPE_FORMAT_NONE);
306
307 if (!nil_format_supports_color_targets(&dev->pdev->info, p_format)) {
308 memset(&clear_value, 0, sizeof(clear_value));
309 util_format_pack_rgba(p_format, clear_value.color.uint32,
310 pColor->uint32, 1);
311
312 unsigned bpp = util_format_get_blocksize(p_format);
313 vk_format = vk_packed_int_format_for_size(bpp);
314 }
315
316 clear_image(cmd, image, imageLayout, vk_format,
317 &clear_value, rangeCount, pRanges);
318 }
319
320 VKAPI_ATTR void VKAPI_CALL
nvk_CmdClearDepthStencilImage(VkCommandBuffer commandBuffer,VkImage _image,VkImageLayout imageLayout,const VkClearDepthStencilValue * pDepthStencil,uint32_t rangeCount,const VkImageSubresourceRange * pRanges)321 nvk_CmdClearDepthStencilImage(VkCommandBuffer commandBuffer,
322 VkImage _image,
323 VkImageLayout imageLayout,
324 const VkClearDepthStencilValue *pDepthStencil,
325 uint32_t rangeCount,
326 const VkImageSubresourceRange *pRanges)
327 {
328 VK_FROM_HANDLE(nvk_cmd_buffer, cmd, commandBuffer);
329 VK_FROM_HANDLE(nvk_image, image, _image);
330
331 const VkClearValue clear_value = {
332 .depthStencil = *pDepthStencil,
333 };
334
335 clear_image(cmd, image, imageLayout, image->vk.format,
336 &clear_value, rangeCount, pRanges);
337 }
338