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