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