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, ®ion->srcSubresource) == 1 &&
352 vk_image_subresource_layer_count(&dst_image->vk, ®ion->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, ®ion);
753
754 radv_cmd_buffer_resolve_rendering_cs(cmd_buffer, src_iview, src_layout, dst_iview, dst_layout, ®ion);
755 break;
756 case RESOLVE_FRAGMENT:
757 radv_decompress_resolve_src(cmd_buffer, src_iview->image, src_layout, ®ion);
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, ®ion);
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, ®ion->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