1 /*
2 * Copyright © 2016 Intel Corporation
3 *
4 * SPDX-License-Identifier: MIT
5 */
6
7 #include <assert.h>
8 #include <stdbool.h>
9
10 #include "nir/nir_builder.h"
11 #include "radv_entrypoints.h"
12 #include "radv_meta.h"
13 #include "sid.h"
14 #include "vk_format.h"
15
16 static nir_shader *
build_nir_fs(struct radv_device * dev)17 build_nir_fs(struct radv_device *dev)
18 {
19 const struct glsl_type *vec4 = glsl_vec4_type();
20 nir_variable *f_color;
21
22 nir_builder b = radv_meta_init_shader(dev, MESA_SHADER_FRAGMENT, "meta_resolve_fs");
23
24 f_color = nir_variable_create(b.shader, nir_var_shader_out, vec4, "f_color");
25 f_color->data.location = FRAG_RESULT_DATA0;
26 nir_store_var(&b, f_color, nir_imm_vec4(&b, 0.0, 0.0, 0.0, 1.0), 0xf);
27
28 return b.shader;
29 }
30
31 struct radv_resolve_key {
32 enum radv_meta_object_key_type type;
33 uint32_t fs_key;
34 };
35
36 static VkResult
get_pipeline(struct radv_device * device,unsigned fs_key,VkPipeline * pipeline_out,VkPipelineLayout * layout_out)37 get_pipeline(struct radv_device *device, unsigned fs_key, VkPipeline *pipeline_out, VkPipelineLayout *layout_out)
38 {
39 const VkFormat format = radv_fs_key_format_exemplars[fs_key];
40 struct radv_resolve_key key;
41 VkResult result;
42
43 result = radv_meta_get_noop_pipeline_layout(device, layout_out);
44 if (result != VK_SUCCESS)
45 return result;
46
47 memset(&key, 0, sizeof(key));
48 key.type = RADV_META_OBJECT_KEY_RESOLVE_HW;
49 key.fs_key = fs_key;
50
51 VkPipeline pipeline_from_cache = vk_meta_lookup_pipeline(&device->meta_state.device, &key, sizeof(key));
52 if (pipeline_from_cache != VK_NULL_HANDLE) {
53 *pipeline_out = pipeline_from_cache;
54 return VK_SUCCESS;
55 }
56
57 nir_shader *vs_module = radv_meta_build_nir_vs_generate_vertices(device);
58 nir_shader *fs_module = build_nir_fs(device);
59
60 const VkGraphicsPipelineCreateInfoRADV radv_info = {
61 .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO_RADV,
62 .custom_blend_mode = V_028808_CB_RESOLVE,
63 };
64
65 const VkGraphicsPipelineCreateInfo pipeline_create_info = {
66 .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
67 .pNext = &radv_info,
68 .stageCount = 2,
69 .pStages =
70 (VkPipelineShaderStageCreateInfo[]){
71 {
72 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
73 .stage = VK_SHADER_STAGE_VERTEX_BIT,
74 .module = vk_shader_module_handle_from_nir(vs_module),
75 .pName = "main",
76 },
77 {
78 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
79 .stage = VK_SHADER_STAGE_FRAGMENT_BIT,
80 .module = vk_shader_module_handle_from_nir(fs_module),
81 .pName = "main",
82 },
83 },
84 .pVertexInputState =
85 &(VkPipelineVertexInputStateCreateInfo){
86 .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
87 .vertexBindingDescriptionCount = 0,
88 .vertexAttributeDescriptionCount = 0,
89 },
90 .pInputAssemblyState =
91 &(VkPipelineInputAssemblyStateCreateInfo){
92 .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
93 .topology = VK_PRIMITIVE_TOPOLOGY_META_RECT_LIST_MESA,
94 .primitiveRestartEnable = false,
95 },
96 .pViewportState =
97 &(VkPipelineViewportStateCreateInfo){
98 .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
99 .viewportCount = 1,
100 .scissorCount = 1,
101 },
102 .pRasterizationState =
103 &(VkPipelineRasterizationStateCreateInfo){
104 .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
105 .depthClampEnable = false,
106 .rasterizerDiscardEnable = false,
107 .polygonMode = VK_POLYGON_MODE_FILL,
108 .cullMode = VK_CULL_MODE_NONE,
109 .frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE,
110 },
111 .pMultisampleState =
112 &(VkPipelineMultisampleStateCreateInfo){
113 .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
114 .rasterizationSamples = 1,
115 .sampleShadingEnable = false,
116 .pSampleMask = NULL,
117 .alphaToCoverageEnable = false,
118 .alphaToOneEnable = false,
119 },
120 .pColorBlendState =
121 &(VkPipelineColorBlendStateCreateInfo){
122 .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
123 .logicOpEnable = false,
124 .attachmentCount = 2,
125 .pAttachments =
126 (VkPipelineColorBlendAttachmentState[]){
127 {
128 .colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT |
129 VK_COLOR_COMPONENT_A_BIT,
130 },
131 {
132 .colorWriteMask = 0,
133
134 }},
135 },
136 .pDynamicState =
137 &(VkPipelineDynamicStateCreateInfo){
138 .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
139 .dynamicStateCount = 2,
140 .pDynamicStates =
141 (VkDynamicState[]){
142 VK_DYNAMIC_STATE_VIEWPORT,
143 VK_DYNAMIC_STATE_SCISSOR,
144 },
145 },
146 .layout = *layout_out,
147 };
148
149 struct vk_meta_rendering_info render = {
150 .color_attachment_count = 2,
151 .color_attachment_formats = {format, format},
152 };
153
154 result = vk_meta_create_graphics_pipeline(&device->vk, &device->meta_state.device, &pipeline_create_info, &render,
155 &key, sizeof(key), pipeline_out);
156
157 ralloc_free(vs_module);
158 ralloc_free(fs_module);
159 return result;
160 }
161
162 static void
emit_resolve(struct radv_cmd_buffer * cmd_buffer,const struct radv_image * src_image,const struct radv_image * dst_image,VkFormat vk_format)163 emit_resolve(struct radv_cmd_buffer *cmd_buffer, const struct radv_image *src_image, const struct radv_image *dst_image,
164 VkFormat vk_format)
165 {
166 struct radv_device *device = radv_cmd_buffer_device(cmd_buffer);
167 VkCommandBuffer cmd_buffer_h = radv_cmd_buffer_to_handle(cmd_buffer);
168 unsigned fs_key = radv_format_meta_fs_key(device, vk_format);
169 VkPipelineLayout layout;
170 VkPipeline pipeline;
171 VkResult result;
172
173 result = get_pipeline(device, fs_key, &pipeline, &layout);
174 if (result != VK_SUCCESS) {
175 vk_command_buffer_set_error(&cmd_buffer->vk, result);
176 return;
177 }
178
179 cmd_buffer->state.flush_bits |= radv_src_access_flush(cmd_buffer, VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
180 VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, 0, src_image, NULL) |
181 radv_dst_access_flush(cmd_buffer, VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
182 VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT, 0, src_image, NULL);
183
184 radv_CmdBindPipeline(cmd_buffer_h, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
185
186 radv_CmdDraw(cmd_buffer_h, 3, 1, 0, 0);
187 cmd_buffer->state.flush_bits |= radv_src_access_flush(cmd_buffer, VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
188 VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, 0, dst_image, NULL);
189 }
190
191 enum radv_resolve_method {
192 RESOLVE_HW,
193 RESOLVE_COMPUTE,
194 RESOLVE_FRAGMENT,
195 };
196
197 static bool
image_hw_resolve_compat(const struct radv_device * device,struct radv_image * src_image,struct radv_image * dst_image)198 image_hw_resolve_compat(const struct radv_device *device, struct radv_image *src_image, struct radv_image *dst_image)
199 {
200 const struct radv_physical_device *pdev = radv_device_physical(device);
201 if (pdev->info.gfx_level >= GFX9) {
202 return dst_image->planes[0].surface.u.gfx9.swizzle_mode == src_image->planes[0].surface.u.gfx9.swizzle_mode;
203 } else {
204 return dst_image->planes[0].surface.micro_tile_mode == src_image->planes[0].surface.micro_tile_mode;
205 }
206 }
207
208 static void
radv_pick_resolve_method_images(struct radv_device * device,struct radv_image * src_image,VkFormat src_format,struct radv_image * dst_image,unsigned dst_level,VkImageLayout dst_image_layout,struct radv_cmd_buffer * cmd_buffer,enum radv_resolve_method * method)209 radv_pick_resolve_method_images(struct radv_device *device, struct radv_image *src_image, VkFormat src_format,
210 struct radv_image *dst_image, unsigned dst_level, VkImageLayout dst_image_layout,
211 struct radv_cmd_buffer *cmd_buffer, enum radv_resolve_method *method)
212
213 {
214 uint32_t queue_mask = radv_image_queue_family_mask(dst_image, cmd_buffer->qf, cmd_buffer->qf);
215
216 if (vk_format_is_color(src_format)) {
217 /* Using the fragment resolve path is currently a hint to
218 * avoid decompressing DCC for partial resolves and
219 * re-initialize it after resolving using compute.
220 * TODO: Add support for layered and int to the fragment path.
221 */
222 if (radv_layout_dcc_compressed(device, dst_image, dst_level, dst_image_layout, queue_mask)) {
223 *method = RESOLVE_FRAGMENT;
224 } else if (!image_hw_resolve_compat(device, src_image, dst_image)) {
225 /* The micro tile mode only needs to match for the HW
226 * resolve path which is the default path for non-DCC
227 * resolves.
228 */
229 *method = RESOLVE_COMPUTE;
230 }
231
232 if (src_format == VK_FORMAT_R16G16_UNORM || src_format == VK_FORMAT_R16G16_SNORM)
233 *method = RESOLVE_COMPUTE;
234 else if (vk_format_is_int(src_format))
235 *method = RESOLVE_COMPUTE;
236 else if (src_image->vk.array_layers > 1 || dst_image->vk.array_layers > 1)
237 *method = RESOLVE_COMPUTE;
238 } else {
239 assert(dst_image_layout == VK_IMAGE_LAYOUT_UNDEFINED);
240 if (src_image->vk.array_layers > 1 || dst_image->vk.array_layers > 1 ||
241 (dst_image->planes[0].surface.flags & RADEON_SURF_NO_RENDER_TARGET))
242 *method = RESOLVE_COMPUTE;
243 else
244 *method = RESOLVE_FRAGMENT;
245 }
246 }
247
248 static void
radv_meta_resolve_hardware_image(struct radv_cmd_buffer * cmd_buffer,struct radv_image * src_image,VkImageLayout src_image_layout,struct radv_image * dst_image,VkImageLayout dst_image_layout,const VkImageResolve2 * region)249 radv_meta_resolve_hardware_image(struct radv_cmd_buffer *cmd_buffer, struct radv_image *src_image,
250 VkImageLayout src_image_layout, struct radv_image *dst_image,
251 VkImageLayout dst_image_layout, const VkImageResolve2 *region)
252 {
253 struct radv_device *device = radv_cmd_buffer_device(cmd_buffer);
254 struct radv_meta_saved_state saved_state;
255
256 radv_meta_save(&saved_state, cmd_buffer, RADV_META_SAVE_GRAPHICS_PIPELINE);
257
258 assert(src_image->vk.samples > 1);
259 assert(dst_image->vk.samples == 1);
260
261 /* From the Vulkan 1.0 spec:
262 *
263 * - The aspectMask member of srcSubresource and dstSubresource must
264 * only contain VK_IMAGE_ASPECT_COLOR_BIT
265 */
266 assert(region->srcSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT);
267 assert(region->dstSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT);
268 /* Multi-layer resolves are handled by compute */
269 assert(vk_image_subresource_layer_count(&src_image->vk, ®ion->srcSubresource) == 1 &&
270 vk_image_subresource_layer_count(&dst_image->vk, ®ion->dstSubresource) == 1);
271 /**
272 * From Vulkan 1.0.6 spec: 18.6 Resolving Multisample Images
273 *
274 * extent is the size in texels of the source image to resolve in width,
275 * height and depth. 1D images use only x and width. 2D images use x, y,
276 * width and height. 3D images use x, y, z, width, height and depth.
277 *
278 * srcOffset and dstOffset select the initial x, y, and z offsets in
279 * texels of the sub-regions of the source and destination image data.
280 * extent is the size in texels of the source image to resolve in width,
281 * height and depth. 1D images use only x and width. 2D images use x, y,
282 * width and height. 3D images use x, y, z, width, height and depth.
283 */
284 const struct VkExtent3D extent = vk_image_sanitize_extent(&src_image->vk, region->extent);
285 const struct VkOffset3D dstOffset = vk_image_sanitize_offset(&dst_image->vk, region->dstOffset);
286
287 uint32_t queue_mask = radv_image_queue_family_mask(dst_image, cmd_buffer->qf, cmd_buffer->qf);
288
289 if (radv_layout_dcc_compressed(device, dst_image, region->dstSubresource.mipLevel, dst_image_layout, queue_mask)) {
290 VkImageSubresourceRange range = {
291 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
292 .baseMipLevel = region->dstSubresource.mipLevel,
293 .levelCount = 1,
294 .baseArrayLayer = 0,
295 .layerCount = 1,
296 };
297
298 cmd_buffer->state.flush_bits |= radv_init_dcc(cmd_buffer, dst_image, &range, 0xffffffff);
299 }
300
301 VkRect2D resolve_area = {
302 .offset = {dstOffset.x, dstOffset.y},
303 .extent = {extent.width, extent.height},
304 };
305
306 radv_CmdSetViewport(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1,
307 &(VkViewport){.x = resolve_area.offset.x,
308 .y = resolve_area.offset.y,
309 .width = resolve_area.extent.width,
310 .height = resolve_area.extent.height,
311 .minDepth = 0.0f,
312 .maxDepth = 1.0f});
313
314 radv_CmdSetScissor(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1, &resolve_area);
315
316 struct radv_image_view src_iview;
317 radv_image_view_init(&src_iview, device,
318 &(VkImageViewCreateInfo){
319 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
320 .image = radv_image_to_handle(src_image),
321 .viewType = VK_IMAGE_VIEW_TYPE_2D,
322 .format = src_image->vk.format,
323 .subresourceRange =
324 {
325 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
326 .baseMipLevel = 0,
327 .levelCount = 1,
328 .baseArrayLayer = 0,
329 .layerCount = 1,
330 },
331 },
332 NULL);
333
334 struct radv_image_view dst_iview;
335 radv_image_view_init(&dst_iview, device,
336 &(VkImageViewCreateInfo){
337 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
338 .image = radv_image_to_handle(dst_image),
339 .viewType = radv_meta_get_view_type(dst_image),
340 .format = dst_image->vk.format,
341 .subresourceRange =
342 {
343 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
344 .baseMipLevel = region->dstSubresource.mipLevel,
345 .levelCount = 1,
346 .baseArrayLayer = 0,
347 .layerCount = 1,
348 },
349 },
350 NULL);
351
352 const VkRenderingAttachmentInfo color_atts[2] = {
353 {
354 .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
355 .imageView = radv_image_view_to_handle(&src_iview),
356 .imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
357 .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
358 .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
359 },
360 {
361 .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
362 .imageView = radv_image_view_to_handle(&dst_iview),
363 .imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
364 .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
365 .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
366 },
367 };
368
369 const VkRenderingInfo rendering_info = {
370 .sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
371 .flags = VK_RENDERING_INPUT_ATTACHMENT_NO_CONCURRENT_WRITES_BIT_MESA,
372 .renderArea = resolve_area,
373 .layerCount = 1,
374 .colorAttachmentCount = 2,
375 .pColorAttachments = color_atts,
376 };
377
378 radv_CmdBeginRendering(radv_cmd_buffer_to_handle(cmd_buffer), &rendering_info);
379
380 emit_resolve(cmd_buffer, src_image, dst_image, dst_iview.vk.format);
381
382 radv_CmdEndRendering(radv_cmd_buffer_to_handle(cmd_buffer));
383
384 radv_image_view_finish(&src_iview);
385 radv_image_view_finish(&dst_iview);
386
387 radv_meta_restore(&saved_state, cmd_buffer);
388 }
389
390 static void
resolve_image(struct radv_cmd_buffer * cmd_buffer,struct radv_image * src_image,VkImageLayout src_image_layout,struct radv_image * dst_image,VkImageLayout dst_image_layout,const VkImageResolve2 * region,enum radv_resolve_method resolve_method)391 resolve_image(struct radv_cmd_buffer *cmd_buffer, struct radv_image *src_image, VkImageLayout src_image_layout,
392 struct radv_image *dst_image, VkImageLayout dst_image_layout, const VkImageResolve2 *region,
393 enum radv_resolve_method resolve_method)
394 {
395 switch (resolve_method) {
396 case RESOLVE_HW:
397 radv_meta_resolve_hardware_image(cmd_buffer, src_image, src_image_layout, dst_image, dst_image_layout, region);
398 break;
399 case RESOLVE_FRAGMENT:
400 radv_decompress_resolve_src(cmd_buffer, src_image, src_image_layout, region);
401
402 radv_meta_resolve_fragment_image(cmd_buffer, src_image, src_image_layout, dst_image, dst_image_layout, region);
403 break;
404 case RESOLVE_COMPUTE:
405 radv_decompress_resolve_src(cmd_buffer, src_image, src_image_layout, region);
406
407 radv_meta_resolve_compute_image(cmd_buffer, src_image, src_image->vk.format, src_image_layout, dst_image,
408 dst_image->vk.format, dst_image_layout, region);
409 break;
410 default:
411 assert(!"Invalid resolve method selected");
412 }
413 }
414
415 VKAPI_ATTR void VKAPI_CALL
radv_CmdResolveImage2(VkCommandBuffer commandBuffer,const VkResolveImageInfo2 * pResolveImageInfo)416 radv_CmdResolveImage2(VkCommandBuffer commandBuffer, const VkResolveImageInfo2 *pResolveImageInfo)
417 {
418 VK_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, commandBuffer);
419 VK_FROM_HANDLE(radv_image, src_image, pResolveImageInfo->srcImage);
420 VK_FROM_HANDLE(radv_image, dst_image, pResolveImageInfo->dstImage);
421 struct radv_device *device = radv_cmd_buffer_device(cmd_buffer);
422 const struct radv_physical_device *pdev = radv_device_physical(device);
423 VkImageLayout src_image_layout = pResolveImageInfo->srcImageLayout;
424 VkImageLayout dst_image_layout = pResolveImageInfo->dstImageLayout;
425 enum radv_resolve_method resolve_method = pdev->info.gfx_level >= GFX11 ? RESOLVE_FRAGMENT : RESOLVE_HW;
426
427 /* we can use the hw resolve only for single full resolves */
428 if (pResolveImageInfo->regionCount == 1) {
429 if (pResolveImageInfo->pRegions[0].srcOffset.x || pResolveImageInfo->pRegions[0].srcOffset.y ||
430 pResolveImageInfo->pRegions[0].srcOffset.z)
431 resolve_method = RESOLVE_COMPUTE;
432 if (pResolveImageInfo->pRegions[0].dstOffset.x || pResolveImageInfo->pRegions[0].dstOffset.y ||
433 pResolveImageInfo->pRegions[0].dstOffset.z)
434 resolve_method = RESOLVE_COMPUTE;
435
436 if (pResolveImageInfo->pRegions[0].extent.width != src_image->vk.extent.width ||
437 pResolveImageInfo->pRegions[0].extent.height != src_image->vk.extent.height ||
438 pResolveImageInfo->pRegions[0].extent.depth != src_image->vk.extent.depth)
439 resolve_method = RESOLVE_COMPUTE;
440 } else
441 resolve_method = RESOLVE_COMPUTE;
442
443 for (uint32_t r = 0; r < pResolveImageInfo->regionCount; r++) {
444 const VkImageResolve2 *region = &pResolveImageInfo->pRegions[r];
445
446 radv_pick_resolve_method_images(device, src_image, src_image->vk.format, dst_image,
447 region->dstSubresource.mipLevel, dst_image_layout, cmd_buffer, &resolve_method);
448
449 resolve_image(cmd_buffer, src_image, src_image_layout, dst_image, dst_image_layout, region, resolve_method);
450 }
451 }
452
453 static void
radv_cmd_buffer_resolve_rendering_hw(struct radv_cmd_buffer * cmd_buffer,struct radv_image_view * src_iview,VkImageLayout src_layout,struct radv_image_view * dst_iview,VkImageLayout dst_layout)454 radv_cmd_buffer_resolve_rendering_hw(struct radv_cmd_buffer *cmd_buffer, struct radv_image_view *src_iview,
455 VkImageLayout src_layout, struct radv_image_view *dst_iview,
456 VkImageLayout dst_layout)
457 {
458 struct radv_device *device = radv_cmd_buffer_device(cmd_buffer);
459 struct radv_meta_saved_state saved_state;
460
461 radv_meta_save(&saved_state, cmd_buffer, RADV_META_SAVE_GRAPHICS_PIPELINE | RADV_META_SAVE_RENDER);
462
463 VkRect2D *resolve_area = &saved_state.render.area;
464
465 radv_CmdSetViewport(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1,
466 &(VkViewport){.x = resolve_area->offset.x,
467 .y = resolve_area->offset.y,
468 .width = resolve_area->extent.width,
469 .height = resolve_area->extent.height,
470 .minDepth = 0.0f,
471 .maxDepth = 1.0f});
472
473 radv_CmdSetScissor(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1, resolve_area);
474
475 struct radv_image *src_img = src_iview->image;
476 struct radv_image *dst_img = dst_iview->image;
477 uint32_t queue_mask = radv_image_queue_family_mask(dst_img, cmd_buffer->qf, cmd_buffer->qf);
478
479 if (radv_layout_dcc_compressed(device, dst_img, dst_iview->vk.base_mip_level, dst_layout, queue_mask)) {
480 VkImageSubresourceRange range = {
481 .aspectMask = dst_iview->vk.aspects,
482 .baseMipLevel = dst_iview->vk.base_mip_level,
483 .levelCount = 1,
484 .baseArrayLayer = 0,
485 .layerCount = 1,
486 };
487
488 cmd_buffer->state.flush_bits |= radv_init_dcc(cmd_buffer, dst_img, &range, 0xffffffff);
489 }
490
491 const VkRenderingAttachmentInfo color_atts[2] = {
492 {
493 .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
494 .imageView = radv_image_view_to_handle(src_iview),
495 .imageLayout = src_layout,
496 .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
497 .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
498 },
499 {
500 .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
501 .imageView = radv_image_view_to_handle(dst_iview),
502 .imageLayout = dst_layout,
503 .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
504 .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
505 },
506 };
507
508 const VkRenderingInfo rendering_info = {
509 .sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
510 .flags = VK_RENDERING_INPUT_ATTACHMENT_NO_CONCURRENT_WRITES_BIT_MESA,
511 .renderArea = saved_state.render.area,
512 .layerCount = 1,
513 .viewMask = saved_state.render.view_mask,
514 .colorAttachmentCount = 2,
515 .pColorAttachments = color_atts,
516 };
517
518 radv_CmdBeginRendering(radv_cmd_buffer_to_handle(cmd_buffer), &rendering_info);
519
520 emit_resolve(cmd_buffer, src_img, dst_img, dst_iview->vk.format);
521
522 radv_CmdEndRendering(radv_cmd_buffer_to_handle(cmd_buffer));
523
524 radv_meta_restore(&saved_state, cmd_buffer);
525 }
526
527 /**
528 * Emit any needed resolves for the current subpass.
529 */
530 void
radv_cmd_buffer_resolve_rendering(struct radv_cmd_buffer * cmd_buffer)531 radv_cmd_buffer_resolve_rendering(struct radv_cmd_buffer *cmd_buffer)
532 {
533 struct radv_device *device = radv_cmd_buffer_device(cmd_buffer);
534 const struct radv_physical_device *pdev = radv_device_physical(device);
535 const struct radv_rendering_state *render = &cmd_buffer->state.render;
536 enum radv_resolve_method resolve_method = pdev->info.gfx_level >= GFX11 ? RESOLVE_FRAGMENT : RESOLVE_HW;
537
538 bool has_color_resolve = false;
539 for (uint32_t i = 0; i < render->color_att_count; ++i) {
540 if (render->color_att[i].resolve_iview != NULL)
541 has_color_resolve = true;
542 }
543 bool has_ds_resolve = render->ds_att.resolve_iview != NULL;
544
545 if (!has_color_resolve && !has_ds_resolve)
546 return;
547
548 radv_describe_begin_render_pass_resolve(cmd_buffer);
549
550 if (render->ds_att.resolve_iview != NULL) {
551 struct radv_image_view *src_iview = render->ds_att.iview;
552 struct radv_image_view *dst_iview = render->ds_att.resolve_iview;
553
554 radv_pick_resolve_method_images(device, src_iview->image, src_iview->vk.format, dst_iview->image,
555 dst_iview->vk.base_mip_level, VK_IMAGE_LAYOUT_UNDEFINED, cmd_buffer,
556 &resolve_method);
557
558 if ((src_iview->vk.aspects & VK_IMAGE_ASPECT_DEPTH_BIT) && render->ds_att.resolve_mode != VK_RESOLVE_MODE_NONE) {
559 if (resolve_method == RESOLVE_FRAGMENT) {
560 radv_depth_stencil_resolve_rendering_fs(cmd_buffer, VK_IMAGE_ASPECT_DEPTH_BIT, render->ds_att.resolve_mode);
561 } else {
562 assert(resolve_method == RESOLVE_COMPUTE);
563 radv_depth_stencil_resolve_rendering_cs(cmd_buffer, VK_IMAGE_ASPECT_DEPTH_BIT, render->ds_att.resolve_mode);
564 }
565 }
566
567 if ((src_iview->vk.aspects & VK_IMAGE_ASPECT_STENCIL_BIT) &&
568 render->ds_att.stencil_resolve_mode != VK_RESOLVE_MODE_NONE) {
569 if (resolve_method == RESOLVE_FRAGMENT) {
570 radv_depth_stencil_resolve_rendering_fs(cmd_buffer, VK_IMAGE_ASPECT_STENCIL_BIT,
571 render->ds_att.stencil_resolve_mode);
572 } else {
573 assert(resolve_method == RESOLVE_COMPUTE);
574 radv_depth_stencil_resolve_rendering_cs(cmd_buffer, VK_IMAGE_ASPECT_STENCIL_BIT,
575 render->ds_att.stencil_resolve_mode);
576 }
577 }
578
579 /* From the Vulkan spec 1.2.165:
580 *
581 * "VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT specifies
582 * write access to a color, resolve, or depth/stencil
583 * resolve attachment during a render pass or via
584 * certain subpass load and store operations."
585 *
586 * Yes, it's counterintuitive but it makes sense because ds
587 * resolve operations happen late at the end of the subpass.
588 *
589 * That said, RADV is wrong because it executes the subpass
590 * end barrier *before* any subpass resolves instead of after.
591 *
592 * TODO: Fix this properly by executing subpass end barriers
593 * after subpass resolves.
594 */
595 cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_FLUSH_AND_INV_DB;
596 if (radv_image_has_htile(dst_iview->image))
597 cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_FLUSH_AND_INV_DB_META;
598 }
599
600 if (has_color_resolve) {
601 uint32_t layer_count = render->layer_count;
602 VkRect2D resolve_area = render->area;
603 struct radv_resolve_barrier barrier;
604
605 if (render->view_mask)
606 layer_count = util_last_bit(render->view_mask);
607
608 /* Resolves happen before the end-of-subpass barriers get executed, so we have to make the
609 * attachment shader-readable.
610 */
611 barrier.src_stage_mask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT;
612 barrier.dst_stage_mask = VK_PIPELINE_STAGE_2_RESOLVE_BIT;
613 barrier.src_access_mask = VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT;
614 barrier.dst_access_mask = VK_ACCESS_2_SHADER_READ_BIT | VK_ACCESS_2_SHADER_WRITE_BIT;
615 radv_emit_resolve_barrier(cmd_buffer, &barrier);
616
617 for (uint32_t i = 0; i < render->color_att_count; ++i) {
618 if (render->color_att[i].resolve_iview == NULL)
619 continue;
620
621 struct radv_image_view *src_iview = render->color_att[i].iview;
622 VkImageLayout src_layout = render->color_att[i].layout;
623 struct radv_image *src_img = src_iview->image;
624 struct radv_image_view *dst_iview = render->color_att[i].resolve_iview;
625 VkImageLayout dst_layout = render->color_att[i].resolve_layout;
626 struct radv_image *dst_img = dst_iview->image;
627
628 radv_pick_resolve_method_images(device, src_img, src_iview->vk.format, dst_img, dst_iview->vk.base_mip_level,
629 dst_layout, cmd_buffer, &resolve_method);
630 VkImageResolve2 region = {
631 .sType = VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2,
632 .extent =
633 {
634 .width = resolve_area.extent.width,
635 .height = resolve_area.extent.height,
636 .depth = 1,
637 },
638 .srcSubresource =
639 (VkImageSubresourceLayers){
640 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
641 .mipLevel = src_iview->vk.base_mip_level,
642 .baseArrayLayer = src_iview->vk.base_array_layer,
643 .layerCount = layer_count,
644 },
645 .dstSubresource =
646 (VkImageSubresourceLayers){
647 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
648 .mipLevel = dst_iview->vk.base_mip_level,
649 .baseArrayLayer = dst_iview->vk.base_array_layer,
650 .layerCount = layer_count,
651 },
652 .srcOffset = {resolve_area.offset.x, resolve_area.offset.y, 0},
653 .dstOffset = {resolve_area.offset.x, resolve_area.offset.y, 0},
654 };
655
656 switch (resolve_method) {
657 case RESOLVE_HW:
658 radv_cmd_buffer_resolve_rendering_hw(cmd_buffer, src_iview, src_layout, dst_iview, dst_layout);
659 break;
660 case RESOLVE_COMPUTE:
661 radv_decompress_resolve_src(cmd_buffer, src_iview->image, src_layout, ®ion);
662
663 radv_cmd_buffer_resolve_rendering_cs(cmd_buffer, src_iview, src_layout, dst_iview, dst_layout, ®ion);
664 break;
665 case RESOLVE_FRAGMENT:
666 radv_decompress_resolve_src(cmd_buffer, src_iview->image, src_layout, ®ion);
667
668 radv_cmd_buffer_resolve_rendering_fs(cmd_buffer, src_iview, src_layout, dst_iview, dst_layout);
669 break;
670 default:
671 unreachable("Invalid resolve method");
672 }
673 }
674 }
675
676 radv_describe_end_render_pass_resolve(cmd_buffer);
677 }
678
679 /**
680 * Decompress CMask/FMask before resolving a multisampled source image inside a
681 * subpass.
682 */
683 void
radv_decompress_resolve_rendering_src(struct radv_cmd_buffer * cmd_buffer)684 radv_decompress_resolve_rendering_src(struct radv_cmd_buffer *cmd_buffer)
685 {
686 const struct radv_rendering_state *render = &cmd_buffer->state.render;
687
688 uint32_t layer_count = render->layer_count;
689 if (render->view_mask)
690 layer_count = util_last_bit(render->view_mask);
691
692 for (uint32_t i = 0; i < render->color_att_count; ++i) {
693 if (render->color_att[i].resolve_iview == NULL)
694 continue;
695
696 struct radv_image_view *src_iview = render->color_att[i].iview;
697 VkImageLayout src_layout = render->color_att[i].layout;
698 struct radv_image *src_image = src_iview->image;
699
700 VkImageResolve2 region = {0};
701 region.sType = VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2;
702 region.srcSubresource.aspectMask = src_iview->vk.aspects;
703 region.srcSubresource.mipLevel = 0;
704 region.srcSubresource.baseArrayLayer = src_iview->vk.base_array_layer;
705 region.srcSubresource.layerCount = layer_count;
706
707 radv_decompress_resolve_src(cmd_buffer, src_image, src_layout, ®ion);
708 }
709 }
710
711 /**
712 * Decompress CMask/FMask before resolving a multisampled source image.
713 */
714 void
radv_decompress_resolve_src(struct radv_cmd_buffer * cmd_buffer,struct radv_image * src_image,VkImageLayout src_image_layout,const VkImageResolve2 * region)715 radv_decompress_resolve_src(struct radv_cmd_buffer *cmd_buffer, struct radv_image *src_image,
716 VkImageLayout src_image_layout, const VkImageResolve2 *region)
717 {
718 VkImageMemoryBarrier2 barrier = {
719 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
720 .srcStageMask = VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT,
721 .srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT,
722 .dstStageMask = VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT,
723 .dstAccessMask = VK_ACCESS_2_TRANSFER_READ_BIT,
724 .oldLayout = src_image_layout,
725 .newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
726 .image = radv_image_to_handle(src_image),
727 .subresourceRange = (VkImageSubresourceRange){
728 .aspectMask = region->srcSubresource.aspectMask,
729 .baseMipLevel = 0,
730 .levelCount = 1,
731 .baseArrayLayer = region->srcSubresource.baseArrayLayer,
732 .layerCount = vk_image_subresource_layer_count(&src_image->vk, ®ion->srcSubresource),
733 }};
734
735 VkSampleLocationsInfoEXT sample_loc_info;
736 if (src_image->vk.create_flags & VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT) {
737 /* If the depth/stencil image uses different sample
738 * locations, we need them during HTILE decompressions.
739 */
740 struct radv_sample_locations_state *sample_locs = &cmd_buffer->state.render.sample_locations;
741
742 sample_loc_info = (VkSampleLocationsInfoEXT){
743 .sType = VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT,
744 .sampleLocationsPerPixel = sample_locs->per_pixel,
745 .sampleLocationGridSize = sample_locs->grid_size,
746 .sampleLocationsCount = sample_locs->count,
747 .pSampleLocations = sample_locs->locations,
748 };
749 barrier.pNext = &sample_loc_info;
750 }
751
752 VkDependencyInfo dep_info = {
753 .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
754 .imageMemoryBarrierCount = 1,
755 .pImageMemoryBarriers = &barrier,
756 };
757
758 radv_CmdPipelineBarrier2(radv_cmd_buffer_to_handle(cmd_buffer), &dep_info);
759 }
760