• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &region->srcSubresource) == 1 &&
270           vk_image_subresource_layer_count(&dst_image->vk, &region->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, &region);
662 
663             radv_cmd_buffer_resolve_rendering_cs(cmd_buffer, src_iview, src_layout, dst_iview, dst_layout, &region);
664             break;
665          case RESOLVE_FRAGMENT:
666             radv_decompress_resolve_src(cmd_buffer, src_iview->image, src_layout, &region);
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, &region);
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, &region->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