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