• 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 "nir/nir_builder.h"
30 #include "sid.h"
31 /**
32  * Vertex attributes used by all pipelines.
33  */
34 struct vertex_attrs {
35 	float position[2]; /**< 3DPRIM_RECTLIST */
36 };
37 
38 /* passthrough vertex shader */
39 static nir_shader *
build_nir_vs(void)40 build_nir_vs(void)
41 {
42 	const struct glsl_type *vec4 = glsl_vec4_type();
43 
44 	nir_builder b;
45 	nir_variable *a_position;
46 	nir_variable *v_position;
47 
48 	nir_builder_init_simple_shader(&b, NULL, MESA_SHADER_VERTEX, NULL);
49 	b.shader->info->name = ralloc_strdup(b.shader, "meta_resolve_vs");
50 
51 	a_position = nir_variable_create(b.shader, nir_var_shader_in, vec4,
52 					 "a_position");
53 	a_position->data.location = VERT_ATTRIB_GENERIC0;
54 
55 	v_position = nir_variable_create(b.shader, nir_var_shader_out, vec4,
56 					 "gl_Position");
57 	v_position->data.location = VARYING_SLOT_POS;
58 
59 	nir_copy_var(&b, v_position, a_position);
60 
61 	return b.shader;
62 }
63 
64 /* simple passthrough shader */
65 static nir_shader *
build_nir_fs(void)66 build_nir_fs(void)
67 {
68 	const struct glsl_type *vec4 = glsl_vec4_type();
69 	nir_builder b;
70 	nir_variable *f_color; /* vec4, fragment output color */
71 
72 	nir_builder_init_simple_shader(&b, NULL, MESA_SHADER_FRAGMENT, NULL);
73 	b.shader->info->name = ralloc_asprintf(b.shader,
74 					       "meta_resolve_fs");
75 
76 	f_color = nir_variable_create(b.shader, nir_var_shader_out, vec4,
77 				      "f_color");
78 	f_color->data.location = FRAG_RESULT_DATA0;
79 	nir_store_var(&b, f_color, nir_imm_vec4(&b, 0.0, 0.0, 0.0, 1.0), 0xf);
80 
81 	return b.shader;
82 }
83 
84 static VkResult
create_pass(struct radv_device * device)85 create_pass(struct radv_device *device)
86 {
87 	VkResult result;
88 	VkDevice device_h = radv_device_to_handle(device);
89 	const VkAllocationCallbacks *alloc = &device->meta_state.alloc;
90 	VkAttachmentDescription attachments[2];
91 	int i;
92 
93 	for (i = 0; i < 2; i++) {
94 		attachments[i].format = VK_FORMAT_UNDEFINED;
95 		attachments[i].samples = 1;
96 		attachments[i].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
97 		attachments[i].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
98 		attachments[i].initialLayout = VK_IMAGE_LAYOUT_GENERAL;
99 		attachments[i].finalLayout = VK_IMAGE_LAYOUT_GENERAL;
100 	}
101 
102 	result = radv_CreateRenderPass(device_h,
103 				       &(VkRenderPassCreateInfo) {
104 					       .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
105 						       .attachmentCount = 2,
106 						       .pAttachments = attachments,
107 						       .subpassCount = 1,
108 								.pSubpasses = &(VkSubpassDescription) {
109 						       .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
110 						       .inputAttachmentCount = 0,
111 						       .colorAttachmentCount = 2,
112 						       .pColorAttachments = (VkAttachmentReference[]) {
113 							       {
114 								       .attachment = 0,
115 								       .layout = VK_IMAGE_LAYOUT_GENERAL,
116 							       },
117 							       {
118 								       .attachment = 1,
119 								       .layout = VK_IMAGE_LAYOUT_GENERAL,
120 							       },
121 						       },
122 						       .pResolveAttachments = NULL,
123 						       .pDepthStencilAttachment = &(VkAttachmentReference) {
124 							       .attachment = VK_ATTACHMENT_UNUSED,
125 						       },
126 						       .preserveAttachmentCount = 0,
127 						       .pPreserveAttachments = NULL,
128 					       },
129 								.dependencyCount = 0,
130 									 },
131 				       alloc,
132 				       &device->meta_state.resolve.pass);
133 
134 	return result;
135 }
136 
137 static VkResult
create_pipeline(struct radv_device * device,VkShaderModule vs_module_h)138 create_pipeline(struct radv_device *device,
139                 VkShaderModule vs_module_h)
140 {
141 	VkResult result;
142 	VkDevice device_h = radv_device_to_handle(device);
143 
144 	struct radv_shader_module fs_module = {
145 		.nir = build_nir_fs(),
146 	};
147 
148 	if (!fs_module.nir) {
149 		/* XXX: Need more accurate error */
150 		result = VK_ERROR_OUT_OF_HOST_MEMORY;
151 		goto cleanup;
152 	}
153 
154 	result = radv_graphics_pipeline_create(device_h,
155 					       radv_pipeline_cache_to_handle(&device->meta_state.cache),
156 					       &(VkGraphicsPipelineCreateInfo) {
157 						       .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
158 						       .stageCount = 2,
159 						       .pStages = (VkPipelineShaderStageCreateInfo[]) {
160 						       {
161 							       .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
162 							       .stage = VK_SHADER_STAGE_VERTEX_BIT,
163 							       .module = vs_module_h,
164 							       .pName = "main",
165 						       },
166 						       {
167 							       .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
168 							       .stage = VK_SHADER_STAGE_FRAGMENT_BIT,
169 							       .module = radv_shader_module_to_handle(&fs_module),
170 							       .pName = "main",
171 						       },
172 					       },
173 					       .pVertexInputState = &(VkPipelineVertexInputStateCreateInfo) {
174 						       .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
175 						       .vertexBindingDescriptionCount = 1,
176 						       .pVertexBindingDescriptions = (VkVertexInputBindingDescription[]) {
177 							       {
178 								       .binding = 0,
179 								       .stride = sizeof(struct vertex_attrs),
180 								       .inputRate = VK_VERTEX_INPUT_RATE_VERTEX
181 							       },
182 						       },
183 						       .vertexAttributeDescriptionCount = 1,
184 						       .pVertexAttributeDescriptions = (VkVertexInputAttributeDescription[]) {
185 							       {
186 								       /* Position */
187 								       .location = 0,
188 								       .binding = 0,
189 								       .format = VK_FORMAT_R32G32_SFLOAT,
190 								       .offset = offsetof(struct vertex_attrs, position),
191 							       },
192 						       },
193 					       },
194 					       .pInputAssemblyState = &(VkPipelineInputAssemblyStateCreateInfo) {
195 						       .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
196 						       .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
197 						       .primitiveRestartEnable = false,
198 					       },
199 					       .pViewportState = &(VkPipelineViewportStateCreateInfo) {
200 						       .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
201 						       .viewportCount = 0,
202 						       .scissorCount = 0,
203 					       },
204 					       .pRasterizationState = &(VkPipelineRasterizationStateCreateInfo) {
205 						       .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
206 						       .depthClampEnable = false,
207 						       .rasterizerDiscardEnable = false,
208 						       .polygonMode = VK_POLYGON_MODE_FILL,
209 						       .cullMode = VK_CULL_MODE_NONE,
210 						       .frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE,
211 					       },
212 					       .pMultisampleState = &(VkPipelineMultisampleStateCreateInfo) {
213 						       .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
214 						       .rasterizationSamples = 1,
215 						       .sampleShadingEnable = false,
216 						       .pSampleMask = NULL,
217 						       .alphaToCoverageEnable = false,
218 						       .alphaToOneEnable = false,
219 					       },
220 					       .pColorBlendState = &(VkPipelineColorBlendStateCreateInfo) {
221 						       .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
222 						       .logicOpEnable = false,
223 						       .attachmentCount = 2,
224 						       .pAttachments = (VkPipelineColorBlendAttachmentState []) {
225 							       {
226 							       .colorWriteMask = VK_COLOR_COMPONENT_R_BIT |
227 									       VK_COLOR_COMPONENT_G_BIT |
228 									       VK_COLOR_COMPONENT_B_BIT |
229 									       VK_COLOR_COMPONENT_A_BIT,
230 							       },
231 							       {
232 							       .colorWriteMask = 0,
233 
234 							       }
235 						       },
236 						},
237 						  .pDynamicState = NULL,
238 																       .renderPass = device->meta_state.resolve.pass,
239 																       .subpass = 0,
240 																       },
241 					       &(struct radv_graphics_pipeline_create_info) {
242 						       .use_rectlist = true,
243 						       .custom_blend_mode = V_028808_CB_RESOLVE,
244 							       },
245 					       &device->meta_state.alloc,
246 					       &device->meta_state.resolve.pipeline);
247 	if (result != VK_SUCCESS)
248 		goto cleanup;
249 
250 	goto cleanup;
251 
252 cleanup:
253 	ralloc_free(fs_module.nir);
254 	return result;
255 }
256 
257 void
radv_device_finish_meta_resolve_state(struct radv_device * device)258 radv_device_finish_meta_resolve_state(struct radv_device *device)
259 {
260 	struct radv_meta_state *state = &device->meta_state;
261 	VkDevice device_h = radv_device_to_handle(device);
262 	VkRenderPass pass_h = device->meta_state.resolve.pass;
263 	const VkAllocationCallbacks *alloc = &device->meta_state.alloc;
264 
265 	if (pass_h)
266 		radv_DestroyRenderPass(device_h, pass_h,
267 					     &device->meta_state.alloc);
268 
269 	VkPipeline pipeline_h = state->resolve.pipeline;
270 	if (pipeline_h) {
271 		radv_DestroyPipeline(device_h, pipeline_h, alloc);
272 	}
273 }
274 
275 VkResult
radv_device_init_meta_resolve_state(struct radv_device * device)276 radv_device_init_meta_resolve_state(struct radv_device *device)
277 {
278 	VkResult res = VK_SUCCESS;
279 
280 	zero(device->meta_state.resolve);
281 
282 	struct radv_shader_module vs_module = { .nir = build_nir_vs() };
283 	if (!vs_module.nir) {
284 		/* XXX: Need more accurate error */
285 		res = VK_ERROR_OUT_OF_HOST_MEMORY;
286 		goto fail;
287 	}
288 
289 	res = create_pass(device);
290 	if (res != VK_SUCCESS)
291 		goto fail;
292 
293 	VkShaderModule vs_module_h = radv_shader_module_to_handle(&vs_module);
294 	res = create_pipeline(device, vs_module_h);
295 	if (res != VK_SUCCESS)
296 		goto fail;
297 
298 	goto cleanup;
299 
300 fail:
301 	radv_device_finish_meta_resolve_state(device);
302 
303 cleanup:
304 	ralloc_free(vs_module.nir);
305 
306 	return res;
307 }
308 
309 static void
emit_resolve(struct radv_cmd_buffer * cmd_buffer,const VkOffset2D * dest_offset,const VkExtent2D * resolve_extent)310 emit_resolve(struct radv_cmd_buffer *cmd_buffer,
311              const VkOffset2D *dest_offset,
312              const VkExtent2D *resolve_extent)
313 {
314 	struct radv_device *device = cmd_buffer->device;
315 	VkCommandBuffer cmd_buffer_h = radv_cmd_buffer_to_handle(cmd_buffer);
316 	uint32_t offset;
317 	const struct vertex_attrs vertex_data[3] = {
318 		{
319 			.position = {
320 				dest_offset->x,
321 				dest_offset->y,
322 			},
323 		},
324 		{
325 			.position = {
326 				dest_offset->x,
327 				dest_offset->y + resolve_extent->height,
328 			},
329 		},
330 		{
331 			.position = {
332 				dest_offset->x + resolve_extent->width,
333 				dest_offset->y,
334 			},
335 		},
336 	};
337 
338 	cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_FLUSH_AND_INV_CB;
339 	radv_cmd_buffer_upload_data(cmd_buffer, sizeof(vertex_data), 16, vertex_data, &offset);
340 	struct radv_buffer vertex_buffer = {
341 		.device = device,
342 		.size = sizeof(vertex_data),
343 		.bo = cmd_buffer->upload.upload_bo,
344 		.offset = offset,
345 	};
346 
347 	VkBuffer vertex_buffer_h = radv_buffer_to_handle(&vertex_buffer);
348 
349 	radv_CmdBindVertexBuffers(cmd_buffer_h,
350 				  /*firstBinding*/ 0,
351 				  /*bindingCount*/ 1,
352 				  (VkBuffer[]) { vertex_buffer_h },
353 				  (VkDeviceSize[]) { 0 });
354 
355 	VkPipeline pipeline_h = device->meta_state.resolve.pipeline;
356 	RADV_FROM_HANDLE(radv_pipeline, pipeline, pipeline_h);
357 
358 	if (cmd_buffer->state.pipeline != pipeline) {
359 		radv_CmdBindPipeline(cmd_buffer_h, VK_PIPELINE_BIND_POINT_GRAPHICS,
360 				     pipeline_h);
361 	}
362 
363 	radv_CmdDraw(cmd_buffer_h, 3, 1, 0, 0);
364 	cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_FLUSH_AND_INV_CB;
365 	si_emit_cache_flush(cmd_buffer);
366 }
367 
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)368 void radv_CmdResolveImage(
369 	VkCommandBuffer                             cmd_buffer_h,
370 	VkImage                                     src_image_h,
371 	VkImageLayout                               src_image_layout,
372 	VkImage                                     dest_image_h,
373 	VkImageLayout                               dest_image_layout,
374 	uint32_t                                    region_count,
375 	const VkImageResolve*                       regions)
376 {
377 	RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, cmd_buffer_h);
378 	RADV_FROM_HANDLE(radv_image, src_image, src_image_h);
379 	RADV_FROM_HANDLE(radv_image, dest_image, dest_image_h);
380 	struct radv_device *device = cmd_buffer->device;
381 	struct radv_meta_saved_state saved_state;
382 	VkDevice device_h = radv_device_to_handle(device);
383 	bool use_compute_resolve = false;
384 
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 			use_compute_resolve = true;
391 		if (regions[0].dstOffset.x ||
392 		    regions[0].dstOffset.y ||
393 		    regions[0].dstOffset.z)
394 			use_compute_resolve = true;
395 
396 		if (regions[0].extent.width != src_image->extent.width ||
397 		    regions[0].extent.height != src_image->extent.height ||
398 		    regions[0].extent.depth != src_image->extent.depth)
399 			use_compute_resolve = true;
400 	} else
401 		use_compute_resolve = true;
402 
403 	if (use_compute_resolve) {
404 
405 		radv_fast_clear_flush_image_inplace(cmd_buffer, src_image);
406 		radv_meta_resolve_compute_image(cmd_buffer,
407 						src_image,
408 						src_image_layout,
409 						dest_image,
410 						dest_image_layout,
411 						region_count, regions);
412 		return;
413 	}
414 
415 	radv_meta_save_graphics_reset_vport_scissor(&saved_state, cmd_buffer);
416 
417 	assert(src_image->samples > 1);
418 	assert(dest_image->samples == 1);
419 
420 	if (src_image->samples >= 16) {
421 		/* See commit aa3f9aaf31e9056a255f9e0472ebdfdaa60abe54 for the
422 		 * glBlitFramebuffer workaround for samples >= 16.
423 		 */
424 		radv_finishme("vkCmdResolveImage: need interpolation workaround when "
425 			      "samples >= 16");
426 	}
427 
428 	if (src_image->array_size > 1)
429 		radv_finishme("vkCmdResolveImage: multisample array images");
430 
431 	for (uint32_t r = 0; r < region_count; ++r) {
432 		const VkImageResolve *region = &regions[r];
433 
434 		/* From the Vulkan 1.0 spec:
435 		 *
436 		 *    - The aspectMask member of srcSubresource and dstSubresource must
437 		 *      only contain VK_IMAGE_ASPECT_COLOR_BIT
438 		 *
439 		 *    - The layerCount member of srcSubresource and dstSubresource must
440 		 *      match
441 		 */
442 		assert(region->srcSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT);
443 		assert(region->dstSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT);
444 		assert(region->srcSubresource.layerCount ==
445 		       region->dstSubresource.layerCount);
446 
447 		const uint32_t src_base_layer =
448 			radv_meta_get_iview_layer(src_image, &region->srcSubresource,
449 						  &region->srcOffset);
450 
451 		const uint32_t dest_base_layer =
452 			radv_meta_get_iview_layer(dest_image, &region->dstSubresource,
453 						  &region->dstOffset);
454 
455 		/**
456 		 * From Vulkan 1.0.6 spec: 18.6 Resolving Multisample Images
457 		 *
458 		 *    extent is the size in texels of the source image to resolve in width,
459 		 *    height and depth. 1D images use only x and width. 2D images use x, y,
460 		 *    width and height. 3D images use x, y, z, width, height and depth.
461 		 *
462 		 *    srcOffset and dstOffset select the initial x, y, and z offsets in
463 		 *    texels of the sub-regions of the source and destination image data.
464 		 *    extent is the size in texels of the source image to resolve in width,
465 		 *    height and depth. 1D images use only x and width. 2D images use x, y,
466 		 *    width and height. 3D images use x, y, z, width, height and depth.
467 		 */
468 		const struct VkExtent3D extent =
469 			radv_sanitize_image_extent(src_image->type, region->extent);
470 		const struct VkOffset3D dstOffset =
471 			radv_sanitize_image_offset(dest_image->type, region->dstOffset);
472 
473 
474 		for (uint32_t layer = 0; layer < region->srcSubresource.layerCount;
475 		     ++layer) {
476 
477 			struct radv_image_view src_iview;
478 			radv_image_view_init(&src_iview, cmd_buffer->device,
479 					     &(VkImageViewCreateInfo) {
480 						     .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
481 							     .image = src_image_h,
482 							     .viewType = radv_meta_get_view_type(src_image),
483 							     .format = src_image->vk_format,
484 							     .subresourceRange = {
485 							     .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
486 							     .baseMipLevel = region->srcSubresource.mipLevel,
487 							     .levelCount = 1,
488 							     .baseArrayLayer = src_base_layer + layer,
489 							     .layerCount = 1,
490 						     },
491 							     },
492 					     cmd_buffer, VK_IMAGE_USAGE_SAMPLED_BIT);
493 
494 			struct radv_image_view dest_iview;
495 			radv_image_view_init(&dest_iview, cmd_buffer->device,
496 					     &(VkImageViewCreateInfo) {
497 						     .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
498 							     .image = dest_image_h,
499 							     .viewType = radv_meta_get_view_type(dest_image),
500 							     .format = dest_image->vk_format,
501 							     .subresourceRange = {
502 							     .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
503 							     .baseMipLevel = region->dstSubresource.mipLevel,
504 							     .levelCount = 1,
505 							     .baseArrayLayer = dest_base_layer + layer,
506 							     .layerCount = 1,
507 						     },
508 							     },
509 					     cmd_buffer, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
510 
511 			VkFramebuffer fb_h;
512 			radv_CreateFramebuffer(device_h,
513 					       &(VkFramebufferCreateInfo) {
514 						       .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
515 							       .attachmentCount = 2,
516 							       .pAttachments = (VkImageView[]) {
517 							       radv_image_view_to_handle(&src_iview),
518 							       radv_image_view_to_handle(&dest_iview),
519 						       },
520 						       .width = radv_minify(dest_image->extent.width,
521 									    region->dstSubresource.mipLevel),
522 						       .height = radv_minify(dest_image->extent.height,
523 									      region->dstSubresource.mipLevel),
524 						       .layers = 1
525 					       },
526 					       &cmd_buffer->pool->alloc,
527 					       &fb_h);
528 
529 			radv_CmdBeginRenderPass(cmd_buffer_h,
530 						      &(VkRenderPassBeginInfo) {
531 							      .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
532 								      .renderPass = device->meta_state.resolve.pass,
533 								      .framebuffer = fb_h,
534 								      .renderArea = {
535 								      .offset = {
536 									      dstOffset.x,
537 									      dstOffset.y,
538 								      },
539 								      .extent = {
540 									      extent.width,
541 									      extent.height,
542 								      }
543 							      },
544 							      .clearValueCount = 0,
545 							      .pClearValues = NULL,
546 						      },
547 						      VK_SUBPASS_CONTENTS_INLINE);
548 
549 			emit_resolve(cmd_buffer,
550 				     &(VkOffset2D) {
551 					     .x = dstOffset.x,
552 					     .y = dstOffset.y,
553 				     },
554 				     &(VkExtent2D) {
555 					     .width = extent.width,
556 					     .height = extent.height,
557 				     });
558 
559 			radv_CmdEndRenderPass(cmd_buffer_h);
560 
561 			radv_DestroyFramebuffer(device_h, fb_h,
562 						&cmd_buffer->pool->alloc);
563 		}
564 	}
565 
566 	radv_meta_restore(&saved_state, cmd_buffer);
567 }
568 
569 /**
570  * Emit any needed resolves for the current subpass.
571  */
572 void
radv_cmd_buffer_resolve_subpass(struct radv_cmd_buffer * cmd_buffer)573 radv_cmd_buffer_resolve_subpass(struct radv_cmd_buffer *cmd_buffer)
574 {
575 	struct radv_framebuffer *fb = cmd_buffer->state.framebuffer;
576 	const struct radv_subpass *subpass = cmd_buffer->state.subpass;
577 	struct radv_meta_saved_state saved_state;
578 
579 	/* FINISHME(perf): Skip clears for resolve attachments.
580 	 *
581 	 * From the Vulkan 1.0 spec:
582 	 *
583 	 *    If the first use of an attachment in a render pass is as a resolve
584 	 *    attachment, then the loadOp is effectively ignored as the resolve is
585 	 *    guaranteed to overwrite all pixels in the render area.
586 	 */
587 
588 	if (!subpass->has_resolve)
589 		return;
590 
591 	radv_meta_save_graphics_reset_vport_scissor(&saved_state, cmd_buffer);
592 
593 	for (uint32_t i = 0; i < subpass->color_count; ++i) {
594 		VkAttachmentReference src_att = subpass->color_attachments[i];
595 		VkAttachmentReference dest_att = subpass->resolve_attachments[i];
596 		struct radv_image *dst_img = cmd_buffer->state.framebuffer->attachments[dest_att.attachment].attachment->image;
597 		if (dest_att.attachment == VK_ATTACHMENT_UNUSED)
598 			continue;
599 
600 		if (dst_img->surface.dcc_size) {
601 			radv_initialize_dcc(cmd_buffer, dst_img, 0xffffffff);
602 			cmd_buffer->state.attachments[dest_att.attachment].current_layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
603 		}
604 
605 		struct radv_subpass resolve_subpass = {
606 			.color_count = 2,
607 			.color_attachments = (VkAttachmentReference[]) { src_att, dest_att },
608 			.depth_stencil_attachment = { .attachment = VK_ATTACHMENT_UNUSED },
609 		};
610 
611 		radv_cmd_buffer_set_subpass(cmd_buffer, &resolve_subpass, false);
612 
613 		/* Subpass resolves must respect the render area. We can ignore the
614 		 * render area here because vkCmdBeginRenderPass set the render area
615 		 * with 3DSTATE_DRAWING_RECTANGLE.
616 		 *
617 		 * XXX(chadv): Does the hardware really respect
618 		 * 3DSTATE_DRAWING_RECTANGLE when draing a 3DPRIM_RECTLIST?
619 		 */
620 		emit_resolve(cmd_buffer,
621 			     &(VkOffset2D) { 0, 0 },
622 			     &(VkExtent2D) { fb->width, fb->height });
623 	}
624 
625 	cmd_buffer->state.subpass = subpass;
626 	radv_meta_restore(&saved_state, cmd_buffer);
627 }
628