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