• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2016 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  */
23 
24 #include <assert.h>
25 #include <stdbool.h>
26 
27 #include "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 *
build_nir_fs(void)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
create_pass(struct radv_device * device,VkFormat vk_format,VkRenderPass * pass)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
create_pipeline(struct radv_device * device,VkShaderModule vs_module_h,VkPipeline * pipeline,VkRenderPass pass)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
radv_device_finish_meta_resolve_state(struct radv_device * device)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 static VkFormat pipeline_formats[] = {
255 	VK_FORMAT_R8G8B8A8_UNORM,
256 	VK_FORMAT_R8G8B8A8_UINT,
257 	VK_FORMAT_R8G8B8A8_SINT,
258 	VK_FORMAT_A2R10G10B10_UINT_PACK32,
259 	VK_FORMAT_A2R10G10B10_SINT_PACK32,
260 	VK_FORMAT_R16G16B16A16_UNORM,
261 	VK_FORMAT_R16G16B16A16_SNORM,
262 	VK_FORMAT_R16G16B16A16_UINT,
263 	VK_FORMAT_R16G16B16A16_SINT,
264 	VK_FORMAT_R32_SFLOAT,
265 	VK_FORMAT_R32G32_SFLOAT,
266 	VK_FORMAT_R32G32B32A32_SFLOAT
267 };
268 
269 VkResult
radv_device_init_meta_resolve_state(struct radv_device * device)270 radv_device_init_meta_resolve_state(struct radv_device *device)
271 {
272 	VkResult res = VK_SUCCESS;
273 	struct radv_meta_state *state = &device->meta_state;
274 	struct radv_shader_module vs_module = { .nir = radv_meta_build_nir_vs_generate_vertices() };
275 	if (!vs_module.nir) {
276 		/* XXX: Need more accurate error */
277 		res = VK_ERROR_OUT_OF_HOST_MEMORY;
278 		goto fail;
279 	}
280 
281 	for (uint32_t i = 0; i < ARRAY_SIZE(pipeline_formats); ++i) {
282 		VkFormat format = pipeline_formats[i];
283 		unsigned fs_key = radv_format_meta_fs_key(format);
284 		res = create_pass(device, format, &state->resolve.pass[fs_key]);
285 		if (res != VK_SUCCESS)
286 			goto fail;
287 
288 		VkShaderModule vs_module_h = radv_shader_module_to_handle(&vs_module);
289 		res = create_pipeline(device, vs_module_h,
290 				      &state->resolve.pipeline[fs_key], state->resolve.pass[fs_key]);
291 		if (res != VK_SUCCESS)
292 			goto fail;
293 	}
294 
295 	goto cleanup;
296 
297 fail:
298 	radv_device_finish_meta_resolve_state(device);
299 
300 cleanup:
301 	ralloc_free(vs_module.nir);
302 
303 	return res;
304 }
305 
306 static void
emit_resolve(struct radv_cmd_buffer * cmd_buffer,VkFormat vk_format,const VkOffset2D * dest_offset,const VkExtent2D * resolve_extent)307 emit_resolve(struct radv_cmd_buffer *cmd_buffer,
308 	     VkFormat vk_format,
309              const VkOffset2D *dest_offset,
310              const VkExtent2D *resolve_extent)
311 {
312 	struct radv_device *device = cmd_buffer->device;
313 	VkCommandBuffer cmd_buffer_h = radv_cmd_buffer_to_handle(cmd_buffer);
314 	unsigned fs_key = radv_format_meta_fs_key(vk_format);
315 
316 	cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_FLUSH_AND_INV_CB;
317 
318 	radv_CmdBindPipeline(cmd_buffer_h, VK_PIPELINE_BIND_POINT_GRAPHICS,
319 			     device->meta_state.resolve.pipeline[fs_key]);
320 
321 	radv_CmdSetViewport(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1, &(VkViewport) {
322 		.x = dest_offset->x,
323 		.y = dest_offset->y,
324 		.width = resolve_extent->width,
325 		.height = resolve_extent->height,
326 		.minDepth = 0.0f,
327 		.maxDepth = 1.0f
328 	});
329 
330 	radv_CmdSetScissor(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1, &(VkRect2D) {
331 		.offset = *dest_offset,
332 		.extent = *resolve_extent,
333 	});
334 
335 	radv_CmdDraw(cmd_buffer_h, 3, 1, 0, 0);
336 	cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_FLUSH_AND_INV_CB;
337 }
338 
339 enum radv_resolve_method {
340 	RESOLVE_HW,
341 	RESOLVE_COMPUTE,
342 	RESOLVE_FRAGMENT,
343 };
344 
radv_pick_resolve_method_images(struct radv_image * src_image,struct radv_image * dest_image,VkImageLayout dest_image_layout,struct radv_cmd_buffer * cmd_buffer,enum radv_resolve_method * method)345 static void radv_pick_resolve_method_images(struct radv_image *src_image,
346 					    struct radv_image *dest_image,
347 					    VkImageLayout dest_image_layout,
348 					    struct radv_cmd_buffer *cmd_buffer,
349 					    enum radv_resolve_method *method)
350 
351 {
352 	uint32_t queue_mask = radv_image_queue_family_mask(dest_image,
353 	                                                   cmd_buffer->queue_family_index,
354 	                                                   cmd_buffer->queue_family_index);
355 
356 	if (src_image->vk_format == VK_FORMAT_R16G16_UNORM ||
357 	    src_image->vk_format == VK_FORMAT_R16G16_SNORM)
358 		*method = RESOLVE_COMPUTE;
359 	else if (vk_format_is_int(src_image->vk_format))
360 		*method = RESOLVE_COMPUTE;
361 
362 	if (radv_layout_dcc_compressed(dest_image, dest_image_layout, queue_mask)) {
363 		*method = RESOLVE_FRAGMENT;
364 	} else if (dest_image->surface.micro_tile_mode != src_image->surface.micro_tile_mode) {
365 		*method = RESOLVE_COMPUTE;
366 	}
367 }
368 
radv_CmdResolveImage(VkCommandBuffer cmd_buffer_h,VkImage src_image_h,VkImageLayout src_image_layout,VkImage dest_image_h,VkImageLayout dest_image_layout,uint32_t region_count,const VkImageResolve * regions)369 void radv_CmdResolveImage(
370 	VkCommandBuffer                             cmd_buffer_h,
371 	VkImage                                     src_image_h,
372 	VkImageLayout                               src_image_layout,
373 	VkImage                                     dest_image_h,
374 	VkImageLayout                               dest_image_layout,
375 	uint32_t                                    region_count,
376 	const VkImageResolve*                       regions)
377 {
378 	RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, cmd_buffer_h);
379 	RADV_FROM_HANDLE(radv_image, src_image, src_image_h);
380 	RADV_FROM_HANDLE(radv_image, dest_image, dest_image_h);
381 	struct radv_device *device = cmd_buffer->device;
382 	struct radv_meta_saved_state saved_state;
383 	VkDevice device_h = radv_device_to_handle(device);
384 	enum radv_resolve_method resolve_method = RESOLVE_HW;
385 	/* we can use the hw resolve only for single full resolves */
386 	if (region_count == 1) {
387 		if (regions[0].srcOffset.x ||
388 		    regions[0].srcOffset.y ||
389 		    regions[0].srcOffset.z)
390 			resolve_method = RESOLVE_COMPUTE;
391 		if (regions[0].dstOffset.x ||
392 		    regions[0].dstOffset.y ||
393 		    regions[0].dstOffset.z)
394 			resolve_method = RESOLVE_COMPUTE;
395 
396 		if (regions[0].extent.width != src_image->info.width ||
397 		    regions[0].extent.height != src_image->info.height ||
398 		    regions[0].extent.depth != src_image->info.depth)
399 			resolve_method = RESOLVE_COMPUTE;
400 	} else
401 		resolve_method = RESOLVE_COMPUTE;
402 
403 	radv_pick_resolve_method_images(src_image, dest_image,
404 					dest_image_layout, cmd_buffer,
405 					&resolve_method);
406 
407 	if (resolve_method == RESOLVE_FRAGMENT) {
408 		radv_meta_resolve_fragment_image(cmd_buffer,
409 						 src_image,
410 						 src_image_layout,
411 						 dest_image,
412 						 dest_image_layout,
413 						 region_count, regions);
414 		return;
415 	}
416 
417 	if (resolve_method == RESOLVE_COMPUTE) {
418 		radv_meta_resolve_compute_image(cmd_buffer,
419 						src_image,
420 						src_image_layout,
421 						dest_image,
422 						dest_image_layout,
423 						region_count, regions);
424 		return;
425 	}
426 
427 	radv_meta_save(&saved_state, cmd_buffer,
428 		       RADV_META_SAVE_GRAPHICS_PIPELINE);
429 
430 	assert(src_image->info.samples > 1);
431 	if (src_image->info.samples <= 1) {
432 		/* this causes GPU hangs if we get past here */
433 		fprintf(stderr, "radv: Illegal resolve operation (src not multisampled), will hang GPU.");
434 		return;
435 	}
436 	assert(dest_image->info.samples == 1);
437 
438 	if (src_image->info.samples >= 16) {
439 		/* See commit aa3f9aaf31e9056a255f9e0472ebdfdaa60abe54 for the
440 		 * glBlitFramebuffer workaround for samples >= 16.
441 		 */
442 		radv_finishme("vkCmdResolveImage: need interpolation workaround when "
443 			      "samples >= 16");
444 	}
445 
446 	if (src_image->info.array_size > 1)
447 		radv_finishme("vkCmdResolveImage: multisample array images");
448 
449 	if (dest_image->surface.dcc_size) {
450 		radv_initialize_dcc(cmd_buffer, dest_image, 0xffffffff);
451 	}
452 	unsigned fs_key = radv_format_meta_fs_key(dest_image->vk_format);
453 	for (uint32_t r = 0; r < region_count; ++r) {
454 		const VkImageResolve *region = &regions[r];
455 
456 		/* From the Vulkan 1.0 spec:
457 		 *
458 		 *    - The aspectMask member of srcSubresource and dstSubresource must
459 		 *      only contain VK_IMAGE_ASPECT_COLOR_BIT
460 		 *
461 		 *    - The layerCount member of srcSubresource and dstSubresource must
462 		 *      match
463 		 */
464 		assert(region->srcSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT);
465 		assert(region->dstSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT);
466 		assert(region->srcSubresource.layerCount ==
467 		       region->dstSubresource.layerCount);
468 
469 		const uint32_t src_base_layer =
470 			radv_meta_get_iview_layer(src_image, &region->srcSubresource,
471 						  &region->srcOffset);
472 
473 		const uint32_t dest_base_layer =
474 			radv_meta_get_iview_layer(dest_image, &region->dstSubresource,
475 						  &region->dstOffset);
476 
477 		/**
478 		 * From Vulkan 1.0.6 spec: 18.6 Resolving Multisample Images
479 		 *
480 		 *    extent is the size in texels of the source image to resolve in width,
481 		 *    height and depth. 1D images use only x and width. 2D images use x, y,
482 		 *    width and height. 3D images use x, y, z, width, height and depth.
483 		 *
484 		 *    srcOffset and dstOffset select the initial x, y, and z offsets in
485 		 *    texels of the sub-regions of the source and destination image data.
486 		 *    extent is the size in texels of the source image to resolve in width,
487 		 *    height and depth. 1D images use only x and width. 2D images use x, y,
488 		 *    width and height. 3D images use x, y, z, width, height and depth.
489 		 */
490 		const struct VkExtent3D extent =
491 			radv_sanitize_image_extent(src_image->type, region->extent);
492 		const struct VkOffset3D dstOffset =
493 			radv_sanitize_image_offset(dest_image->type, region->dstOffset);
494 
495 
496 		for (uint32_t layer = 0; layer < region->srcSubresource.layerCount;
497 		     ++layer) {
498 
499 			struct radv_image_view src_iview;
500 			radv_image_view_init(&src_iview, cmd_buffer->device,
501 					     &(VkImageViewCreateInfo) {
502 						     .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
503 							     .image = src_image_h,
504 							     .viewType = radv_meta_get_view_type(src_image),
505 							     .format = src_image->vk_format,
506 							     .subresourceRange = {
507 							     .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
508 							     .baseMipLevel = region->srcSubresource.mipLevel,
509 							     .levelCount = 1,
510 							     .baseArrayLayer = src_base_layer + layer,
511 							     .layerCount = 1,
512 						     },
513 					     });
514 
515 			struct radv_image_view dest_iview;
516 			radv_image_view_init(&dest_iview, cmd_buffer->device,
517 					     &(VkImageViewCreateInfo) {
518 						     .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
519 							     .image = dest_image_h,
520 							     .viewType = radv_meta_get_view_type(dest_image),
521 							     .format = dest_image->vk_format,
522 							     .subresourceRange = {
523 							     .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
524 							     .baseMipLevel = region->dstSubresource.mipLevel,
525 							     .levelCount = 1,
526 							     .baseArrayLayer = dest_base_layer + layer,
527 							     .layerCount = 1,
528 						     },
529 					      });
530 
531 			VkFramebuffer fb_h;
532 			radv_CreateFramebuffer(device_h,
533 					       &(VkFramebufferCreateInfo) {
534 						       .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
535 							       .attachmentCount = 2,
536 							       .pAttachments = (VkImageView[]) {
537 							       radv_image_view_to_handle(&src_iview),
538 							       radv_image_view_to_handle(&dest_iview),
539 						       },
540 						       .width = radv_minify(dest_image->info.width,
541 									    region->dstSubresource.mipLevel),
542 						       .height = radv_minify(dest_image->info.height,
543 									      region->dstSubresource.mipLevel),
544 						       .layers = 1
545 					       },
546 					       &cmd_buffer->pool->alloc,
547 					       &fb_h);
548 
549 			radv_CmdBeginRenderPass(cmd_buffer_h,
550 						      &(VkRenderPassBeginInfo) {
551 							      .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
552 								      .renderPass = device->meta_state.resolve.pass[fs_key],
553 								      .framebuffer = fb_h,
554 								      .renderArea = {
555 								      .offset = {
556 									      dstOffset.x,
557 									      dstOffset.y,
558 								      },
559 								      .extent = {
560 									      extent.width,
561 									      extent.height,
562 								      }
563 							      },
564 							      .clearValueCount = 0,
565 							      .pClearValues = NULL,
566 						      },
567 						      VK_SUBPASS_CONTENTS_INLINE);
568 
569 			emit_resolve(cmd_buffer,
570 				     dest_iview.vk_format,
571 				     &(VkOffset2D) {
572 					     .x = dstOffset.x,
573 					     .y = dstOffset.y,
574 				     },
575 				     &(VkExtent2D) {
576 					     .width = extent.width,
577 					     .height = extent.height,
578 				     });
579 
580 			radv_CmdEndRenderPass(cmd_buffer_h);
581 
582 			radv_DestroyFramebuffer(device_h, fb_h,
583 						&cmd_buffer->pool->alloc);
584 		}
585 	}
586 
587 	radv_meta_restore(&saved_state, cmd_buffer);
588 }
589 
590 /**
591  * Emit any needed resolves for the current subpass.
592  */
593 void
radv_cmd_buffer_resolve_subpass(struct radv_cmd_buffer * cmd_buffer)594 radv_cmd_buffer_resolve_subpass(struct radv_cmd_buffer *cmd_buffer)
595 {
596 	struct radv_framebuffer *fb = cmd_buffer->state.framebuffer;
597 	const struct radv_subpass *subpass = cmd_buffer->state.subpass;
598 	struct radv_meta_saved_state saved_state;
599 	enum radv_resolve_method resolve_method = RESOLVE_HW;
600 
601 	/* FINISHME(perf): Skip clears for resolve attachments.
602 	 *
603 	 * From the Vulkan 1.0 spec:
604 	 *
605 	 *    If the first use of an attachment in a render pass is as a resolve
606 	 *    attachment, then the loadOp is effectively ignored as the resolve is
607 	 *    guaranteed to overwrite all pixels in the render area.
608 	 */
609 
610 	if (!subpass->has_resolve)
611 		return;
612 
613 	for (uint32_t i = 0; i < subpass->color_count; ++i) {
614 		VkAttachmentReference src_att = subpass->color_attachments[i];
615 		VkAttachmentReference dest_att = subpass->resolve_attachments[i];
616 
617 		if (src_att.attachment == VK_ATTACHMENT_UNUSED ||
618 		    dest_att.attachment == VK_ATTACHMENT_UNUSED)
619 			continue;
620 
621 		struct radv_image *dst_img = cmd_buffer->state.framebuffer->attachments[dest_att.attachment].attachment->image;
622 		struct radv_image *src_img = cmd_buffer->state.framebuffer->attachments[src_att.attachment].attachment->image;
623 
624 		radv_pick_resolve_method_images(src_img, dst_img, dest_att.layout, cmd_buffer, &resolve_method);
625 		if (resolve_method == RESOLVE_FRAGMENT) {
626 			break;
627 		}
628 	}
629 
630 	if (resolve_method == RESOLVE_COMPUTE) {
631 		radv_cmd_buffer_resolve_subpass_cs(cmd_buffer);
632 		return;
633 	} else if (resolve_method == RESOLVE_FRAGMENT) {
634 		radv_cmd_buffer_resolve_subpass_fs(cmd_buffer);
635 		return;
636 	}
637 
638 	radv_meta_save(&saved_state, cmd_buffer,
639 		       RADV_META_SAVE_GRAPHICS_PIPELINE);
640 
641 	for (uint32_t i = 0; i < subpass->color_count; ++i) {
642 		VkAttachmentReference src_att = subpass->color_attachments[i];
643 		VkAttachmentReference dest_att = subpass->resolve_attachments[i];
644 
645 		if (src_att.attachment == VK_ATTACHMENT_UNUSED ||
646 		    dest_att.attachment == VK_ATTACHMENT_UNUSED)
647 			continue;
648 
649 		struct radv_image *dst_img = cmd_buffer->state.framebuffer->attachments[dest_att.attachment].attachment->image;
650 
651 		if (dst_img->surface.dcc_size) {
652 			radv_initialize_dcc(cmd_buffer, dst_img, 0xffffffff);
653 			cmd_buffer->state.attachments[dest_att.attachment].current_layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
654 		}
655 
656 		struct radv_subpass resolve_subpass = {
657 			.color_count = 2,
658 			.color_attachments = (VkAttachmentReference[]) { src_att, dest_att },
659 			.depth_stencil_attachment = { .attachment = VK_ATTACHMENT_UNUSED },
660 		};
661 
662 		radv_cmd_buffer_set_subpass(cmd_buffer, &resolve_subpass, false);
663 
664 		emit_resolve(cmd_buffer,
665 			     dst_img->vk_format,
666 			     &(VkOffset2D) { 0, 0 },
667 			     &(VkExtent2D) { fb->width, fb->height });
668 	}
669 
670 	cmd_buffer->state.subpass = subpass;
671 	radv_meta_restore(&saved_state, cmd_buffer);
672 }
673