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