• 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_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