radv: Pass through render loop detection to internal layout decisions.
[mesa.git] / src / amd / vulkan / radv_meta_resolve.c
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 "radv_meta.h"
28 #include "radv_private.h"
29 #include "vk_format.h"
30 #include "nir/nir_builder.h"
31 #include "sid.h"
32
33 /* emit 0, 0, 0, 1 */
34 static nir_shader *
35 build_nir_fs(void)
36 {
37 const struct glsl_type *vec4 = glsl_vec4_type();
38 nir_builder b;
39 nir_variable *f_color; /* vec4, fragment output color */
40
41 nir_builder_init_simple_shader(&b, NULL, MESA_SHADER_FRAGMENT, NULL);
42 b.shader->info.name = ralloc_asprintf(b.shader,
43 "meta_resolve_fs");
44
45 f_color = nir_variable_create(b.shader, nir_var_shader_out, vec4,
46 "f_color");
47 f_color->data.location = FRAG_RESULT_DATA0;
48 nir_store_var(&b, f_color, nir_imm_vec4(&b, 0.0, 0.0, 0.0, 1.0), 0xf);
49
50 return b.shader;
51 }
52
53 static VkResult
54 create_pass(struct radv_device *device, VkFormat vk_format, VkRenderPass *pass)
55 {
56 VkResult result;
57 VkDevice device_h = radv_device_to_handle(device);
58 const VkAllocationCallbacks *alloc = &device->meta_state.alloc;
59 VkAttachmentDescription attachments[2];
60 int i;
61
62 for (i = 0; i < 2; i++) {
63 attachments[i].format = vk_format;
64 attachments[i].samples = 1;
65 attachments[i].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
66 attachments[i].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
67 }
68 attachments[0].initialLayout = VK_IMAGE_LAYOUT_GENERAL;
69 attachments[0].finalLayout = VK_IMAGE_LAYOUT_GENERAL;
70 attachments[1].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
71 attachments[1].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
72
73 result = radv_CreateRenderPass(device_h,
74 &(VkRenderPassCreateInfo) {
75 .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
76 .attachmentCount = 2,
77 .pAttachments = attachments,
78 .subpassCount = 1,
79 .pSubpasses = &(VkSubpassDescription) {
80 .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
81 .inputAttachmentCount = 0,
82 .colorAttachmentCount = 2,
83 .pColorAttachments = (VkAttachmentReference[]) {
84 {
85 .attachment = 0,
86 .layout = VK_IMAGE_LAYOUT_GENERAL,
87 },
88 {
89 .attachment = 1,
90 .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
91 },
92 },
93 .pResolveAttachments = NULL,
94 .pDepthStencilAttachment = &(VkAttachmentReference) {
95 .attachment = VK_ATTACHMENT_UNUSED,
96 },
97 .preserveAttachmentCount = 0,
98 .pPreserveAttachments = NULL,
99 },
100 .dependencyCount = 0,
101 },
102 alloc,
103 pass);
104
105 return result;
106 }
107
108 static VkResult
109 create_pipeline(struct radv_device *device,
110 VkShaderModule vs_module_h,
111 VkPipeline *pipeline,
112 VkRenderPass pass)
113 {
114 VkResult result;
115 VkDevice device_h = radv_device_to_handle(device);
116
117 struct radv_shader_module fs_module = {
118 .nir = build_nir_fs(),
119 };
120
121 if (!fs_module.nir) {
122 /* XXX: Need more accurate error */
123 result = VK_ERROR_OUT_OF_HOST_MEMORY;
124 goto cleanup;
125 }
126
127 VkPipelineLayoutCreateInfo pl_create_info = {
128 .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
129 .setLayoutCount = 0,
130 .pSetLayouts = NULL,
131 .pushConstantRangeCount = 0,
132 .pPushConstantRanges = NULL,
133 };
134
135 if (!device->meta_state.resolve.p_layout) {
136 result = radv_CreatePipelineLayout(radv_device_to_handle(device),
137 &pl_create_info,
138 &device->meta_state.alloc,
139 &device->meta_state.resolve.p_layout);
140 if (result != VK_SUCCESS)
141 goto cleanup;
142 }
143
144 result = radv_graphics_pipeline_create(device_h,
145 radv_pipeline_cache_to_handle(&device->meta_state.cache),
146 &(VkGraphicsPipelineCreateInfo) {
147 .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
148 .stageCount = 2,
149 .pStages = (VkPipelineShaderStageCreateInfo[]) {
150 {
151 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
152 .stage = VK_SHADER_STAGE_VERTEX_BIT,
153 .module = vs_module_h,
154 .pName = "main",
155 },
156 {
157 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
158 .stage = VK_SHADER_STAGE_FRAGMENT_BIT,
159 .module = radv_shader_module_to_handle(&fs_module),
160 .pName = "main",
161 },
162 },
163 .pVertexInputState = &(VkPipelineVertexInputStateCreateInfo) {
164 .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
165 .vertexBindingDescriptionCount = 0,
166 .vertexAttributeDescriptionCount = 0,
167 },
168 .pInputAssemblyState = &(VkPipelineInputAssemblyStateCreateInfo) {
169 .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
170 .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
171 .primitiveRestartEnable = false,
172 },
173 .pViewportState = &(VkPipelineViewportStateCreateInfo) {
174 .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
175 .viewportCount = 1,
176 .scissorCount = 1,
177 },
178 .pRasterizationState = &(VkPipelineRasterizationStateCreateInfo) {
179 .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
180 .depthClampEnable = false,
181 .rasterizerDiscardEnable = false,
182 .polygonMode = VK_POLYGON_MODE_FILL,
183 .cullMode = VK_CULL_MODE_NONE,
184 .frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE,
185 },
186 .pMultisampleState = &(VkPipelineMultisampleStateCreateInfo) {
187 .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
188 .rasterizationSamples = 1,
189 .sampleShadingEnable = false,
190 .pSampleMask = NULL,
191 .alphaToCoverageEnable = false,
192 .alphaToOneEnable = false,
193 },
194 .pColorBlendState = &(VkPipelineColorBlendStateCreateInfo) {
195 .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
196 .logicOpEnable = false,
197 .attachmentCount = 2,
198 .pAttachments = (VkPipelineColorBlendAttachmentState []) {
199 {
200 .colorWriteMask = VK_COLOR_COMPONENT_R_BIT |
201 VK_COLOR_COMPONENT_G_BIT |
202 VK_COLOR_COMPONENT_B_BIT |
203 VK_COLOR_COMPONENT_A_BIT,
204 },
205 {
206 .colorWriteMask = 0,
207
208 }
209 },
210 },
211 .pDynamicState = &(VkPipelineDynamicStateCreateInfo) {
212 .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
213 .dynamicStateCount = 2,
214 .pDynamicStates = (VkDynamicState[]) {
215 VK_DYNAMIC_STATE_VIEWPORT,
216 VK_DYNAMIC_STATE_SCISSOR,
217 },
218 },
219 .layout = device->meta_state.resolve.p_layout,
220 .renderPass = pass,
221 .subpass = 0,
222 },
223 &(struct radv_graphics_pipeline_create_info) {
224 .use_rectlist = true,
225 .custom_blend_mode = V_028808_CB_RESOLVE,
226 },
227 &device->meta_state.alloc, pipeline);
228 if (result != VK_SUCCESS)
229 goto cleanup;
230
231 goto cleanup;
232
233 cleanup:
234 ralloc_free(fs_module.nir);
235 return result;
236 }
237
238 void
239 radv_device_finish_meta_resolve_state(struct radv_device *device)
240 {
241 struct radv_meta_state *state = &device->meta_state;
242
243 for (uint32_t j = 0; j < NUM_META_FS_KEYS; j++) {
244 radv_DestroyRenderPass(radv_device_to_handle(device),
245 state->resolve.pass[j], &state->alloc);
246 radv_DestroyPipeline(radv_device_to_handle(device),
247 state->resolve.pipeline[j], &state->alloc);
248 }
249 radv_DestroyPipelineLayout(radv_device_to_handle(device),
250 state->resolve.p_layout, &state->alloc);
251
252 }
253
254 VkResult
255 radv_device_init_meta_resolve_state(struct radv_device *device, bool on_demand)
256 {
257 if (on_demand)
258 return VK_SUCCESS;
259
260 VkResult res = VK_SUCCESS;
261 struct radv_meta_state *state = &device->meta_state;
262 struct radv_shader_module vs_module = { .nir = radv_meta_build_nir_vs_generate_vertices() };
263 if (!vs_module.nir) {
264 /* XXX: Need more accurate error */
265 res = VK_ERROR_OUT_OF_HOST_MEMORY;
266 goto fail;
267 }
268
269 for (uint32_t i = 0; i < NUM_META_FS_KEYS; ++i) {
270 VkFormat format = radv_fs_key_format_exemplars[i];
271 unsigned fs_key = radv_format_meta_fs_key(format);
272 res = create_pass(device, format, &state->resolve.pass[fs_key]);
273 if (res != VK_SUCCESS)
274 goto fail;
275
276 VkShaderModule vs_module_h = radv_shader_module_to_handle(&vs_module);
277 res = create_pipeline(device, vs_module_h,
278 &state->resolve.pipeline[fs_key], state->resolve.pass[fs_key]);
279 if (res != VK_SUCCESS)
280 goto fail;
281 }
282
283 goto cleanup;
284
285 fail:
286 radv_device_finish_meta_resolve_state(device);
287
288 cleanup:
289 ralloc_free(vs_module.nir);
290
291 return res;
292 }
293
294 static void
295 emit_resolve(struct radv_cmd_buffer *cmd_buffer,
296 VkFormat vk_format,
297 const VkOffset2D *dest_offset,
298 const VkExtent2D *resolve_extent)
299 {
300 struct radv_device *device = cmd_buffer->device;
301 VkCommandBuffer cmd_buffer_h = radv_cmd_buffer_to_handle(cmd_buffer);
302 unsigned fs_key = radv_format_meta_fs_key(vk_format);
303
304 cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_FLUSH_AND_INV_CB;
305
306 radv_CmdBindPipeline(cmd_buffer_h, VK_PIPELINE_BIND_POINT_GRAPHICS,
307 device->meta_state.resolve.pipeline[fs_key]);
308
309 radv_CmdSetViewport(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1, &(VkViewport) {
310 .x = dest_offset->x,
311 .y = dest_offset->y,
312 .width = resolve_extent->width,
313 .height = resolve_extent->height,
314 .minDepth = 0.0f,
315 .maxDepth = 1.0f
316 });
317
318 radv_CmdSetScissor(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1, &(VkRect2D) {
319 .offset = *dest_offset,
320 .extent = *resolve_extent,
321 });
322
323 radv_CmdDraw(cmd_buffer_h, 3, 1, 0, 0);
324 cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_FLUSH_AND_INV_CB;
325 }
326
327 enum radv_resolve_method {
328 RESOLVE_HW,
329 RESOLVE_COMPUTE,
330 RESOLVE_FRAGMENT,
331 };
332
333 static void radv_pick_resolve_method_images(struct radv_image *src_image,
334 VkFormat src_format,
335 struct radv_image *dest_image,
336 VkImageLayout dest_image_layout,
337 bool dest_render_loop,
338 struct radv_cmd_buffer *cmd_buffer,
339 enum radv_resolve_method *method)
340
341 {
342 uint32_t queue_mask = radv_image_queue_family_mask(dest_image,
343 cmd_buffer->queue_family_index,
344 cmd_buffer->queue_family_index);
345
346 if (vk_format_is_color(src_format)) {
347 if (src_format == VK_FORMAT_R16G16_UNORM ||
348 src_format == VK_FORMAT_R16G16_SNORM)
349 *method = RESOLVE_COMPUTE;
350 else if (vk_format_is_int(src_format))
351 *method = RESOLVE_COMPUTE;
352 else if (src_image->info.array_size > 1 ||
353 dest_image->info.array_size > 1)
354 *method = RESOLVE_COMPUTE;
355
356 if (radv_layout_dcc_compressed(dest_image, dest_image_layout,
357 dest_render_loop, queue_mask)) {
358 *method = RESOLVE_FRAGMENT;
359 } else if (dest_image->planes[0].surface.micro_tile_mode !=
360 src_image->planes[0].surface.micro_tile_mode) {
361 *method = RESOLVE_COMPUTE;
362 }
363 } else {
364 if (src_image->info.array_size > 1 ||
365 dest_image->info.array_size > 1)
366 *method = RESOLVE_COMPUTE;
367 else
368 *method = RESOLVE_FRAGMENT;
369 }
370 }
371
372 static VkResult
373 build_resolve_pipeline(struct radv_device *device,
374 unsigned fs_key)
375 {
376 VkResult result = VK_SUCCESS;
377
378 if (device->meta_state.resolve.pipeline[fs_key])
379 return result;
380
381 mtx_lock(&device->meta_state.mtx);
382 if (device->meta_state.resolve.pipeline[fs_key]) {
383 mtx_unlock(&device->meta_state.mtx);
384 return result;
385 }
386
387 struct radv_shader_module vs_module = { .nir = radv_meta_build_nir_vs_generate_vertices() };
388
389 result = create_pass(device, radv_fs_key_format_exemplars[fs_key], &device->meta_state.resolve.pass[fs_key]);
390 if (result != VK_SUCCESS)
391 goto fail;
392
393 VkShaderModule vs_module_h = radv_shader_module_to_handle(&vs_module);
394 result = create_pipeline(device, vs_module_h, &device->meta_state.resolve.pipeline[fs_key], device->meta_state.resolve.pass[fs_key]);
395
396 fail:
397 ralloc_free(vs_module.nir);
398 mtx_unlock(&device->meta_state.mtx);
399 return result;
400 }
401
402 void radv_CmdResolveImage(
403 VkCommandBuffer cmd_buffer_h,
404 VkImage src_image_h,
405 VkImageLayout src_image_layout,
406 VkImage dest_image_h,
407 VkImageLayout dest_image_layout,
408 uint32_t region_count,
409 const VkImageResolve* regions)
410 {
411 RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, cmd_buffer_h);
412 RADV_FROM_HANDLE(radv_image, src_image, src_image_h);
413 RADV_FROM_HANDLE(radv_image, dest_image, dest_image_h);
414 struct radv_device *device = cmd_buffer->device;
415 struct radv_meta_saved_state saved_state;
416 VkDevice device_h = radv_device_to_handle(device);
417 enum radv_resolve_method resolve_method = RESOLVE_HW;
418 /* we can use the hw resolve only for single full resolves */
419 if (region_count == 1) {
420 if (regions[0].srcOffset.x ||
421 regions[0].srcOffset.y ||
422 regions[0].srcOffset.z)
423 resolve_method = RESOLVE_COMPUTE;
424 if (regions[0].dstOffset.x ||
425 regions[0].dstOffset.y ||
426 regions[0].dstOffset.z)
427 resolve_method = RESOLVE_COMPUTE;
428
429 if (regions[0].extent.width != src_image->info.width ||
430 regions[0].extent.height != src_image->info.height ||
431 regions[0].extent.depth != src_image->info.depth)
432 resolve_method = RESOLVE_COMPUTE;
433 } else
434 resolve_method = RESOLVE_COMPUTE;
435
436 radv_pick_resolve_method_images(src_image, src_image->vk_format,
437 dest_image, dest_image_layout,
438 false, cmd_buffer, &resolve_method);
439
440 if (resolve_method == RESOLVE_FRAGMENT) {
441 radv_meta_resolve_fragment_image(cmd_buffer,
442 src_image,
443 src_image_layout,
444 dest_image,
445 dest_image_layout,
446 region_count, regions);
447 return;
448 }
449
450 if (resolve_method == RESOLVE_COMPUTE) {
451 radv_meta_resolve_compute_image(cmd_buffer,
452 src_image,
453 src_image->vk_format,
454 src_image_layout,
455 dest_image,
456 dest_image->vk_format,
457 dest_image_layout,
458 region_count, regions);
459 return;
460 }
461
462 radv_meta_save(&saved_state, cmd_buffer,
463 RADV_META_SAVE_GRAPHICS_PIPELINE);
464
465 assert(src_image->info.samples > 1);
466 if (src_image->info.samples <= 1) {
467 /* this causes GPU hangs if we get past here */
468 fprintf(stderr, "radv: Illegal resolve operation (src not multisampled), will hang GPU.");
469 return;
470 }
471 assert(dest_image->info.samples == 1);
472
473 if (src_image->info.array_size > 1)
474 radv_finishme("vkCmdResolveImage: multisample array images");
475
476 unsigned fs_key = radv_format_meta_fs_key(dest_image->vk_format);
477 for (uint32_t r = 0; r < region_count; ++r) {
478 const VkImageResolve *region = &regions[r];
479
480 /* From the Vulkan 1.0 spec:
481 *
482 * - The aspectMask member of srcSubresource and dstSubresource must
483 * only contain VK_IMAGE_ASPECT_COLOR_BIT
484 *
485 * - The layerCount member of srcSubresource and dstSubresource must
486 * match
487 */
488 assert(region->srcSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT);
489 assert(region->dstSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT);
490 assert(region->srcSubresource.layerCount ==
491 region->dstSubresource.layerCount);
492
493 const uint32_t src_base_layer =
494 radv_meta_get_iview_layer(src_image, &region->srcSubresource,
495 &region->srcOffset);
496
497 const uint32_t dest_base_layer =
498 radv_meta_get_iview_layer(dest_image, &region->dstSubresource,
499 &region->dstOffset);
500
501 /**
502 * From Vulkan 1.0.6 spec: 18.6 Resolving Multisample Images
503 *
504 * extent is the size in texels of the source image to resolve in width,
505 * height and depth. 1D images use only x and width. 2D images use x, y,
506 * width and height. 3D images use x, y, z, width, height and depth.
507 *
508 * srcOffset and dstOffset select the initial x, y, and z offsets in
509 * texels of the sub-regions of the source and destination image data.
510 * extent is the size in texels of the source image to resolve in width,
511 * height and depth. 1D images use only x and width. 2D images use x, y,
512 * width and height. 3D images use x, y, z, width, height and depth.
513 */
514 const struct VkExtent3D extent =
515 radv_sanitize_image_extent(src_image->type, region->extent);
516 const struct VkOffset3D dstOffset =
517 radv_sanitize_image_offset(dest_image->type, region->dstOffset);
518
519 if (radv_dcc_enabled(dest_image, region->dstSubresource.mipLevel)) {
520 VkImageSubresourceRange range = {
521 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
522 .baseMipLevel = region->dstSubresource.mipLevel,
523 .levelCount = 1,
524 .baseArrayLayer = dest_base_layer,
525 .layerCount = region->dstSubresource.layerCount,
526 };
527
528 radv_initialize_dcc(cmd_buffer, dest_image, &range, 0xffffffff);
529 }
530
531 for (uint32_t layer = 0; layer < region->srcSubresource.layerCount;
532 ++layer) {
533
534 VkResult ret = build_resolve_pipeline(device, fs_key);
535 if (ret != VK_SUCCESS) {
536 cmd_buffer->record_result = ret;
537 break;
538 }
539
540 struct radv_image_view src_iview;
541 radv_image_view_init(&src_iview, cmd_buffer->device,
542 &(VkImageViewCreateInfo) {
543 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
544 .image = src_image_h,
545 .viewType = radv_meta_get_view_type(src_image),
546 .format = src_image->vk_format,
547 .subresourceRange = {
548 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
549 .baseMipLevel = region->srcSubresource.mipLevel,
550 .levelCount = 1,
551 .baseArrayLayer = src_base_layer + layer,
552 .layerCount = 1,
553 },
554 });
555
556 struct radv_image_view dest_iview;
557 radv_image_view_init(&dest_iview, cmd_buffer->device,
558 &(VkImageViewCreateInfo) {
559 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
560 .image = dest_image_h,
561 .viewType = radv_meta_get_view_type(dest_image),
562 .format = dest_image->vk_format,
563 .subresourceRange = {
564 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
565 .baseMipLevel = region->dstSubresource.mipLevel,
566 .levelCount = 1,
567 .baseArrayLayer = dest_base_layer + layer,
568 .layerCount = 1,
569 },
570 });
571
572 VkFramebuffer fb_h;
573 radv_CreateFramebuffer(device_h,
574 &(VkFramebufferCreateInfo) {
575 .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
576 .attachmentCount = 2,
577 .pAttachments = (VkImageView[]) {
578 radv_image_view_to_handle(&src_iview),
579 radv_image_view_to_handle(&dest_iview),
580 },
581 .width = radv_minify(dest_image->info.width,
582 region->dstSubresource.mipLevel),
583 .height = radv_minify(dest_image->info.height,
584 region->dstSubresource.mipLevel),
585 .layers = 1
586 },
587 &cmd_buffer->pool->alloc,
588 &fb_h);
589
590 radv_CmdBeginRenderPass(cmd_buffer_h,
591 &(VkRenderPassBeginInfo) {
592 .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
593 .renderPass = device->meta_state.resolve.pass[fs_key],
594 .framebuffer = fb_h,
595 .renderArea = {
596 .offset = {
597 dstOffset.x,
598 dstOffset.y,
599 },
600 .extent = {
601 extent.width,
602 extent.height,
603 }
604 },
605 .clearValueCount = 0,
606 .pClearValues = NULL,
607 },
608 VK_SUBPASS_CONTENTS_INLINE);
609
610 emit_resolve(cmd_buffer,
611 dest_iview.vk_format,
612 &(VkOffset2D) {
613 .x = dstOffset.x,
614 .y = dstOffset.y,
615 },
616 &(VkExtent2D) {
617 .width = extent.width,
618 .height = extent.height,
619 });
620
621 radv_CmdEndRenderPass(cmd_buffer_h);
622
623 radv_DestroyFramebuffer(device_h, fb_h,
624 &cmd_buffer->pool->alloc);
625 }
626 }
627
628 radv_meta_restore(&saved_state, cmd_buffer);
629 }
630
631 /**
632 * Emit any needed resolves for the current subpass.
633 */
634 void
635 radv_cmd_buffer_resolve_subpass(struct radv_cmd_buffer *cmd_buffer)
636 {
637 struct radv_framebuffer *fb = cmd_buffer->state.framebuffer;
638 const struct radv_subpass *subpass = cmd_buffer->state.subpass;
639 struct radv_meta_saved_state saved_state;
640 enum radv_resolve_method resolve_method = RESOLVE_HW;
641
642 if (subpass->ds_resolve_attachment) {
643 struct radv_subpass_attachment src_att = *subpass->depth_stencil_attachment;
644 struct radv_subpass_attachment dst_att = *subpass->ds_resolve_attachment;
645 struct radv_image_view *src_iview =
646 cmd_buffer->state.attachments[src_att.attachment].iview;
647 struct radv_image_view *dst_iview =
648 cmd_buffer->state.attachments[dst_att.attachment].iview;
649
650 radv_pick_resolve_method_images(src_iview->image,
651 src_iview->vk_format,
652 dst_iview->image,
653 dst_att.layout,
654 dst_att.in_render_loop,
655 cmd_buffer,
656 &resolve_method);
657
658 if ((src_iview->aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) &&
659 subpass->depth_resolve_mode != VK_RESOLVE_MODE_NONE_KHR) {
660 if (resolve_method == RESOLVE_FRAGMENT) {
661 radv_depth_stencil_resolve_subpass_fs(cmd_buffer,
662 VK_IMAGE_ASPECT_DEPTH_BIT,
663 subpass->depth_resolve_mode);
664 } else {
665 assert(resolve_method == RESOLVE_COMPUTE);
666 radv_depth_stencil_resolve_subpass_cs(cmd_buffer,
667 VK_IMAGE_ASPECT_DEPTH_BIT,
668 subpass->depth_resolve_mode);
669 }
670 }
671
672 if ((src_iview->aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) &&
673 subpass->stencil_resolve_mode != VK_RESOLVE_MODE_NONE_KHR) {
674 if (resolve_method == RESOLVE_FRAGMENT) {
675 radv_depth_stencil_resolve_subpass_fs(cmd_buffer,
676 VK_IMAGE_ASPECT_STENCIL_BIT,
677 subpass->stencil_resolve_mode);
678 } else {
679 assert(resolve_method == RESOLVE_COMPUTE);
680 radv_depth_stencil_resolve_subpass_cs(cmd_buffer,
681 VK_IMAGE_ASPECT_STENCIL_BIT,
682 subpass->stencil_resolve_mode);
683 }
684 }
685 }
686
687 if (!subpass->has_color_resolve)
688 return;
689
690 for (uint32_t i = 0; i < subpass->color_count; ++i) {
691 struct radv_subpass_attachment src_att = subpass->color_attachments[i];
692 struct radv_subpass_attachment dest_att = subpass->resolve_attachments[i];
693
694 if (dest_att.attachment == VK_ATTACHMENT_UNUSED)
695 continue;
696
697 /* Make sure to not clear color attachments after resolves. */
698 cmd_buffer->state.attachments[dest_att.attachment].pending_clear_aspects = 0;
699
700 struct radv_image *dst_img = cmd_buffer->state.attachments[dest_att.attachment].iview->image;
701 struct radv_image_view *src_iview= cmd_buffer->state.attachments[src_att.attachment].iview;
702 struct radv_image *src_img = src_iview->image;
703
704 radv_pick_resolve_method_images(src_img, src_iview->vk_format,
705 dst_img, dest_att.layout,
706 dest_att.in_render_loop,
707 cmd_buffer, &resolve_method);
708
709 if (resolve_method == RESOLVE_FRAGMENT) {
710 break;
711 }
712 }
713
714 if (resolve_method == RESOLVE_COMPUTE) {
715 radv_cmd_buffer_resolve_subpass_cs(cmd_buffer);
716 return;
717 } else if (resolve_method == RESOLVE_FRAGMENT) {
718 radv_cmd_buffer_resolve_subpass_fs(cmd_buffer);
719 return;
720 }
721
722 radv_meta_save(&saved_state, cmd_buffer,
723 RADV_META_SAVE_GRAPHICS_PIPELINE);
724
725 for (uint32_t i = 0; i < subpass->color_count; ++i) {
726 struct radv_subpass_attachment src_att = subpass->color_attachments[i];
727 struct radv_subpass_attachment dest_att = subpass->resolve_attachments[i];
728
729 if (dest_att.attachment == VK_ATTACHMENT_UNUSED)
730 continue;
731
732 struct radv_image_view *dest_iview = cmd_buffer->state.attachments[dest_att.attachment].iview;
733 struct radv_image *dst_img = dest_iview->image;
734
735 if (radv_dcc_enabled(dst_img, dest_iview->base_mip)) {
736 VkImageSubresourceRange range = {
737 .aspectMask = dest_iview->aspect_mask,
738 .baseMipLevel = dest_iview->base_mip,
739 .levelCount = dest_iview->level_count,
740 .baseArrayLayer = dest_iview->base_layer,
741 .layerCount = dest_iview->layer_count,
742 };
743
744 radv_initialize_dcc(cmd_buffer, dst_img, &range, 0xffffffff);
745 cmd_buffer->state.attachments[dest_att.attachment].current_layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
746 }
747
748 struct radv_subpass resolve_subpass = {
749 .color_count = 2,
750 .color_attachments = (struct radv_subpass_attachment[]) { src_att, dest_att },
751 .depth_stencil_attachment = NULL,
752 };
753
754 radv_cmd_buffer_set_subpass(cmd_buffer, &resolve_subpass);
755
756 VkResult ret = build_resolve_pipeline(cmd_buffer->device, radv_format_meta_fs_key(dest_iview->vk_format));
757 if (ret != VK_SUCCESS) {
758 cmd_buffer->record_result = ret;
759 continue;
760 }
761
762 emit_resolve(cmd_buffer,
763 dest_iview->vk_format,
764 &(VkOffset2D) { 0, 0 },
765 &(VkExtent2D) { fb->width, fb->height });
766 }
767
768 radv_cmd_buffer_set_subpass(cmd_buffer, subpass);
769
770 radv_meta_restore(&saved_state, cmd_buffer);
771 }
772
773 /**
774 * Decompress CMask/FMask before resolving a multisampled source image inside a
775 * subpass.
776 */
777 void
778 radv_decompress_resolve_subpass_src(struct radv_cmd_buffer *cmd_buffer)
779 {
780 const struct radv_subpass *subpass = cmd_buffer->state.subpass;
781 struct radv_framebuffer *fb = cmd_buffer->state.framebuffer;
782 uint32_t layer_count = fb->layers;
783
784 if (subpass->view_mask)
785 layer_count = util_last_bit(subpass->view_mask);
786
787 for (uint32_t i = 0; i < subpass->color_count; ++i) {
788 struct radv_subpass_attachment src_att = subpass->color_attachments[i];
789 struct radv_subpass_attachment dest_att = subpass->resolve_attachments[i];
790
791 if (dest_att.attachment == VK_ATTACHMENT_UNUSED)
792 continue;
793
794 struct radv_image_view *src_iview = cmd_buffer->state.attachments[src_att.attachment].iview;
795 struct radv_image *src_image = src_iview->image;
796
797 VkImageResolve region = {};
798 region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
799 region.srcSubresource.mipLevel = 0;
800 region.srcSubresource.baseArrayLayer = src_iview->base_layer;
801 region.srcSubresource.layerCount = layer_count;
802
803 radv_decompress_resolve_src(cmd_buffer, src_image,
804 src_att.layout, 1, &region);
805 }
806
807 if (subpass->ds_resolve_attachment) {
808 struct radv_subpass_attachment src_att = *subpass->depth_stencil_attachment;
809 struct radv_image_view *src_iview = fb->attachments[src_att.attachment];
810 struct radv_image *src_image = src_iview->image;
811
812 VkImageResolve region = {};
813 region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
814 region.srcSubresource.mipLevel = 0;
815 region.srcSubresource.baseArrayLayer = src_iview->base_layer;
816 region.srcSubresource.layerCount = layer_count;
817
818 radv_decompress_resolve_src(cmd_buffer, src_image,
819 src_att.layout, 1, &region);
820 }
821 }
822
823 static struct radv_sample_locations_state *
824 radv_get_resolve_sample_locations(struct radv_cmd_buffer *cmd_buffer)
825 {
826 struct radv_cmd_state *state = &cmd_buffer->state;
827 uint32_t subpass_id = radv_get_subpass_id(cmd_buffer);
828
829 for (uint32_t i = 0; i < state->num_subpass_sample_locs; i++) {
830 if (state->subpass_sample_locs[i].subpass_idx == subpass_id)
831 return &state->subpass_sample_locs[i].sample_location;
832 }
833
834 return NULL;
835 }
836
837 /**
838 * Decompress CMask/FMask before resolving a multisampled source image.
839 */
840 void
841 radv_decompress_resolve_src(struct radv_cmd_buffer *cmd_buffer,
842 struct radv_image *src_image,
843 VkImageLayout src_image_layout,
844 uint32_t region_count,
845 const VkImageResolve *regions)
846 {
847 for (uint32_t r = 0; r < region_count; ++r) {
848 const VkImageResolve *region = &regions[r];
849 const uint32_t src_base_layer =
850 radv_meta_get_iview_layer(src_image, &region->srcSubresource,
851 &region->srcOffset);
852
853 VkImageMemoryBarrier barrier = {};
854 barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
855 barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
856 barrier.oldLayout = src_image_layout;
857 barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
858 barrier.image = radv_image_to_handle(src_image);
859 barrier.subresourceRange = (VkImageSubresourceRange) {
860 .aspectMask = region->srcSubresource.aspectMask,
861 .baseMipLevel = region->srcSubresource.mipLevel,
862 .levelCount = 1,
863 .baseArrayLayer = src_base_layer,
864 .layerCount = region->srcSubresource.layerCount,
865 };
866
867 if (src_image->flags & VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT) {
868 /* If the depth/stencil image uses different sample
869 * locations, we need them during HTILE decompressions.
870 */
871 struct radv_sample_locations_state *sample_locs =
872 radv_get_resolve_sample_locations(cmd_buffer);
873
874 barrier.pNext = &(VkSampleLocationsInfoEXT) {
875 .sType = VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT,
876 .sampleLocationsPerPixel = sample_locs->per_pixel,
877 .sampleLocationGridSize = sample_locs->grid_size,
878 .sampleLocationsCount = sample_locs->count,
879 .pSampleLocations = sample_locs->locations,
880 };
881 }
882
883 radv_CmdPipelineBarrier(radv_cmd_buffer_to_handle(cmd_buffer),
884 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
885 VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
886 false, 0, NULL, 0, NULL, 1, &barrier);
887 }
888 }