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