Home | History | Annotate | Download | only in vulkan
      1 /*
      2  * Copyright  2016 Dave Airlie
      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 
     25 #include <assert.h>
     26 #include <stdbool.h>
     27 
     28 #include "radv_meta.h"
     29 #include "radv_private.h"
     30 #include "nir/nir_builder.h"
     31 #include "sid.h"
     32 #include "vk_format.h"
     33 
     34 static nir_shader *
     35 build_nir_vertex_shader(void)
     36 {
     37 	const struct glsl_type *vec4 = glsl_vec4_type();
     38 	nir_builder b;
     39 
     40 	nir_builder_init_simple_shader(&b, NULL, MESA_SHADER_VERTEX, NULL);
     41 	b.shader->info.name = ralloc_strdup(b.shader, "meta_resolve_vs");
     42 
     43 	nir_variable *pos_out = nir_variable_create(b.shader, nir_var_shader_out,
     44 						    vec4, "gl_Position");
     45 	pos_out->data.location = VARYING_SLOT_POS;
     46 
     47 	nir_ssa_def *outvec = radv_meta_gen_rect_vertices(&b);
     48 
     49 	nir_store_var(&b, pos_out, outvec, 0xf);
     50 	return b.shader;
     51 }
     52 
     53 static nir_shader *
     54 build_resolve_fragment_shader(struct radv_device *dev, bool is_integer, int samples)
     55 {
     56 	nir_builder b;
     57 	char name[64];
     58 	const struct glsl_type *vec2 = glsl_vector_type(GLSL_TYPE_FLOAT, 2);
     59 	const struct glsl_type *vec4 = glsl_vec4_type();
     60 	const struct glsl_type *sampler_type = glsl_sampler_type(GLSL_SAMPLER_DIM_MS,
     61 								 false,
     62 								 false,
     63 								 GLSL_TYPE_FLOAT);
     64 
     65 	snprintf(name, 64, "meta_resolve_fs-%d-%s", samples, is_integer ? "int" : "float");
     66 	nir_builder_init_simple_shader(&b, NULL, MESA_SHADER_FRAGMENT, NULL);
     67 	b.shader->info.name = ralloc_strdup(b.shader, name);
     68 
     69 	nir_variable *input_img = nir_variable_create(b.shader, nir_var_uniform,
     70 						      sampler_type, "s_tex");
     71 	input_img->data.descriptor_set = 0;
     72 	input_img->data.binding = 0;
     73 
     74 	nir_variable *fs_pos_in = nir_variable_create(b.shader, nir_var_shader_in, vec2, "fs_pos_in");
     75 	fs_pos_in->data.location = VARYING_SLOT_POS;
     76 
     77 	nir_variable *color_out = nir_variable_create(b.shader, nir_var_shader_out,
     78 						      vec4, "f_color");
     79 	color_out->data.location = FRAG_RESULT_DATA0;
     80 
     81 	nir_ssa_def *pos_in = nir_load_var(&b, fs_pos_in);
     82 	nir_intrinsic_instr *src_offset = nir_intrinsic_instr_create(b.shader, nir_intrinsic_load_push_constant);
     83 	nir_intrinsic_set_base(src_offset, 0);
     84 	nir_intrinsic_set_range(src_offset, 8);
     85 	src_offset->src[0] = nir_src_for_ssa(nir_imm_int(&b, 0));
     86 	src_offset->num_components = 2;
     87 	nir_ssa_dest_init(&src_offset->instr, &src_offset->dest, 2, 32, "src_offset");
     88 	nir_builder_instr_insert(&b, &src_offset->instr);
     89 
     90 	nir_ssa_def *pos_int = nir_f2i32(&b, pos_in);
     91 
     92 	nir_ssa_def *img_coord = nir_channels(&b, nir_iadd(&b, pos_int, &src_offset->dest.ssa), 0x3);
     93 	nir_variable *color = nir_local_variable_create(b.impl, glsl_vec4_type(), "color");
     94 
     95 	radv_meta_build_resolve_shader_core(&b, is_integer, samples, input_img,
     96 	                                    color, img_coord);
     97 
     98 	nir_ssa_def *outval = nir_load_var(&b, color);
     99 	nir_store_var(&b, color_out, outval, 0xf);
    100 	return b.shader;
    101 }
    102 
    103 
    104 static VkResult
    105 create_layout(struct radv_device *device)
    106 {
    107 	VkResult result;
    108 	/*
    109 	 * one descriptors for the image being sampled
    110 	 */
    111 	VkDescriptorSetLayoutCreateInfo ds_create_info = {
    112 		.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
    113 		.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR,
    114 		.bindingCount = 1,
    115 		.pBindings = (VkDescriptorSetLayoutBinding[]) {
    116 			{
    117 				.binding = 0,
    118 				.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
    119 				.descriptorCount = 1,
    120 				.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
    121 				.pImmutableSamplers = NULL
    122 			},
    123 		}
    124 	};
    125 
    126 	result = radv_CreateDescriptorSetLayout(radv_device_to_handle(device),
    127 						&ds_create_info,
    128 						&device->meta_state.alloc,
    129 						&device->meta_state.resolve_fragment.ds_layout);
    130 	if (result != VK_SUCCESS)
    131 		goto fail;
    132 
    133 
    134 	VkPipelineLayoutCreateInfo pl_create_info = {
    135 		.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
    136 		.setLayoutCount = 1,
    137 		.pSetLayouts = &device->meta_state.resolve_fragment.ds_layout,
    138 		.pushConstantRangeCount = 1,
    139 		.pPushConstantRanges = &(VkPushConstantRange){VK_SHADER_STAGE_FRAGMENT_BIT, 0, 8},
    140 	};
    141 
    142 	result = radv_CreatePipelineLayout(radv_device_to_handle(device),
    143 					  &pl_create_info,
    144 					  &device->meta_state.alloc,
    145 					  &device->meta_state.resolve_fragment.p_layout);
    146 	if (result != VK_SUCCESS)
    147 		goto fail;
    148 	return VK_SUCCESS;
    149 fail:
    150 	return result;
    151 }
    152 
    153 static const VkPipelineVertexInputStateCreateInfo normal_vi_create_info = {
    154 	.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
    155 	.vertexBindingDescriptionCount = 0,
    156 	.vertexAttributeDescriptionCount = 0,
    157 };
    158 
    159 static VkFormat pipeline_formats[] = {
    160    VK_FORMAT_R8G8B8A8_UNORM,
    161    VK_FORMAT_R8G8B8A8_UINT,
    162    VK_FORMAT_R8G8B8A8_SINT,
    163    VK_FORMAT_A2R10G10B10_UINT_PACK32,
    164    VK_FORMAT_A2R10G10B10_SINT_PACK32,
    165    VK_FORMAT_R16G16B16A16_UNORM,
    166    VK_FORMAT_R16G16B16A16_SNORM,
    167    VK_FORMAT_R16G16B16A16_UINT,
    168    VK_FORMAT_R16G16B16A16_SINT,
    169    VK_FORMAT_R32_SFLOAT,
    170    VK_FORMAT_R32G32_SFLOAT,
    171    VK_FORMAT_R32G32B32A32_SFLOAT
    172 };
    173 
    174 static VkResult
    175 create_resolve_pipeline(struct radv_device *device,
    176 			int samples_log2,
    177 			VkFormat format)
    178 {
    179 	VkResult result;
    180 	bool is_integer = false;
    181 	uint32_t samples = 1 << samples_log2;
    182 	unsigned fs_key = radv_format_meta_fs_key(format);
    183 	const VkPipelineVertexInputStateCreateInfo *vi_create_info;
    184 	vi_create_info = &normal_vi_create_info;
    185 	if (vk_format_is_int(format))
    186 		is_integer = true;
    187 
    188 	struct radv_shader_module fs = { .nir = NULL };
    189 	fs.nir = build_resolve_fragment_shader(device, is_integer, samples);
    190 	struct radv_shader_module vs = {
    191 		.nir = build_nir_vertex_shader(),
    192 	};
    193 
    194 	VkRenderPass *rp = &device->meta_state.resolve_fragment.rc[samples_log2].render_pass[fs_key][0];
    195 
    196 	assert(!*rp);
    197 
    198 	VkPipeline *pipeline = &device->meta_state.resolve_fragment.rc[samples_log2].pipeline[fs_key];
    199 	assert(!*pipeline);
    200 
    201 	VkPipelineShaderStageCreateInfo pipeline_shader_stages[] = {
    202 		{
    203 			.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
    204 			.stage = VK_SHADER_STAGE_VERTEX_BIT,
    205 			.module = radv_shader_module_to_handle(&vs),
    206 			.pName = "main",
    207 			.pSpecializationInfo = NULL
    208 		}, {
    209 			.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
    210 			.stage = VK_SHADER_STAGE_FRAGMENT_BIT,
    211 			.module = radv_shader_module_to_handle(&fs),
    212 			.pName = "main",
    213 			.pSpecializationInfo = NULL
    214 		},
    215 	};
    216 
    217 
    218 	for (unsigned dst_layout = 0; dst_layout < RADV_META_DST_LAYOUT_COUNT; ++dst_layout) {
    219 		VkImageLayout layout = radv_meta_dst_layout_to_layout(dst_layout);
    220 		result = radv_CreateRenderPass(radv_device_to_handle(device),
    221 					&(VkRenderPassCreateInfo) {
    222 						.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
    223 						.attachmentCount = 1,
    224 						.pAttachments = &(VkAttachmentDescription) {
    225 							.format = format,
    226 							.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
    227 							.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
    228 							.initialLayout = layout,
    229 							.finalLayout = layout,
    230 						},
    231 						.subpassCount = 1,
    232 						.pSubpasses = &(VkSubpassDescription) {
    233 							.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
    234 							.inputAttachmentCount = 0,
    235 							.colorAttachmentCount = 1,
    236 							.pColorAttachments = &(VkAttachmentReference) {
    237 								.attachment = 0,
    238 								.layout = layout,
    239 							},
    240 						.pResolveAttachments = NULL,
    241 						.pDepthStencilAttachment = &(VkAttachmentReference) {
    242 							.attachment = VK_ATTACHMENT_UNUSED,
    243 							.layout = VK_IMAGE_LAYOUT_GENERAL,
    244 						},
    245 						.preserveAttachmentCount = 1,
    246 						.pPreserveAttachments = (uint32_t[]) { 0 },
    247 					},
    248 					.dependencyCount = 0,
    249 				}, &device->meta_state.alloc, rp + dst_layout);
    250 	}
    251 
    252 
    253 	const VkGraphicsPipelineCreateInfo vk_pipeline_info = {
    254 		.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
    255 		.stageCount = ARRAY_SIZE(pipeline_shader_stages),
    256 		.pStages = pipeline_shader_stages,
    257 		.pVertexInputState = vi_create_info,
    258 		.pInputAssemblyState = &(VkPipelineInputAssemblyStateCreateInfo) {
    259 			.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
    260 			.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
    261 			.primitiveRestartEnable = false,
    262 		},
    263 		.pViewportState = &(VkPipelineViewportStateCreateInfo) {
    264 			.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
    265 			.viewportCount = 1,
    266 			.scissorCount = 1,
    267 		},
    268 		.pRasterizationState = &(VkPipelineRasterizationStateCreateInfo) {
    269 			.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
    270 			.rasterizerDiscardEnable = false,
    271 			.polygonMode = VK_POLYGON_MODE_FILL,
    272 			.cullMode = VK_CULL_MODE_NONE,
    273 			.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE
    274 		},
    275 		.pMultisampleState = &(VkPipelineMultisampleStateCreateInfo) {
    276 			.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
    277 			.rasterizationSamples = 1,
    278 			.sampleShadingEnable = false,
    279 			.pSampleMask = (VkSampleMask[]) { UINT32_MAX },
    280 		},
    281 		.pColorBlendState = &(VkPipelineColorBlendStateCreateInfo) {
    282 			.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
    283 			.attachmentCount = 1,
    284 			.pAttachments = (VkPipelineColorBlendAttachmentState []) {
    285 				{ .colorWriteMask =
    286 				  VK_COLOR_COMPONENT_A_BIT |
    287 				  VK_COLOR_COMPONENT_R_BIT |
    288 				  VK_COLOR_COMPONENT_G_BIT |
    289 				  VK_COLOR_COMPONENT_B_BIT },
    290 			}
    291 		},
    292 		.pDynamicState = &(VkPipelineDynamicStateCreateInfo) {
    293 			.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
    294 			.dynamicStateCount = 9,
    295 			.pDynamicStates = (VkDynamicState[]) {
    296 				VK_DYNAMIC_STATE_VIEWPORT,
    297 				VK_DYNAMIC_STATE_SCISSOR,
    298 				VK_DYNAMIC_STATE_LINE_WIDTH,
    299 				VK_DYNAMIC_STATE_DEPTH_BIAS,
    300 				VK_DYNAMIC_STATE_BLEND_CONSTANTS,
    301 				VK_DYNAMIC_STATE_DEPTH_BOUNDS,
    302 				VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK,
    303 				VK_DYNAMIC_STATE_STENCIL_WRITE_MASK,
    304 				VK_DYNAMIC_STATE_STENCIL_REFERENCE,
    305 			},
    306 		},
    307 		.flags = 0,
    308 		.layout = device->meta_state.resolve_fragment.p_layout,
    309 		.renderPass = *rp,
    310 		.subpass = 0,
    311 	};
    312 
    313 	const struct radv_graphics_pipeline_create_info radv_pipeline_info = {
    314 		.use_rectlist = true
    315 	};
    316 
    317 	result = radv_graphics_pipeline_create(radv_device_to_handle(device),
    318 					       radv_pipeline_cache_to_handle(&device->meta_state.cache),
    319 					       &vk_pipeline_info, &radv_pipeline_info,
    320 					       &device->meta_state.alloc,
    321 					       pipeline);
    322 	ralloc_free(vs.nir);
    323 	ralloc_free(fs.nir);
    324 
    325 	return result;
    326 }
    327 
    328 VkResult
    329 radv_device_init_meta_resolve_fragment_state(struct radv_device *device)
    330 {
    331 	VkResult res;
    332 
    333 	res = create_layout(device);
    334 	if (res != VK_SUCCESS)
    335 		goto fail;
    336 
    337 	for (uint32_t i = 0; i < MAX_SAMPLES_LOG2; ++i) {
    338 		for (unsigned j = 0; j < ARRAY_SIZE(pipeline_formats); ++j) {
    339 			res = create_resolve_pipeline(device, i, pipeline_formats[j]);
    340 			if (res != VK_SUCCESS)
    341 				goto fail;
    342 		}
    343 	}
    344 
    345 	return VK_SUCCESS;
    346 fail:
    347 	radv_device_finish_meta_resolve_fragment_state(device);
    348 	return res;
    349 }
    350 
    351 void
    352 radv_device_finish_meta_resolve_fragment_state(struct radv_device *device)
    353 {
    354 	struct radv_meta_state *state = &device->meta_state;
    355 	for (uint32_t i = 0; i < MAX_SAMPLES_LOG2; ++i) {
    356 		for (unsigned j = 0; j < NUM_META_FS_KEYS; ++j) {
    357 			for(unsigned k =0; k < RADV_META_DST_LAYOUT_COUNT; ++k) {
    358 				radv_DestroyRenderPass(radv_device_to_handle(device),
    359 				                       state->resolve_fragment.rc[i].render_pass[j][k],
    360 				                       &state->alloc);
    361 			}
    362 			radv_DestroyPipeline(radv_device_to_handle(device),
    363 					     state->resolve_fragment.rc[i].pipeline[j],
    364 					     &state->alloc);
    365 		}
    366 	}
    367 
    368 	radv_DestroyDescriptorSetLayout(radv_device_to_handle(device),
    369 					state->resolve_fragment.ds_layout,
    370 					&state->alloc);
    371 	radv_DestroyPipelineLayout(radv_device_to_handle(device),
    372 				   state->resolve_fragment.p_layout,
    373 				   &state->alloc);
    374 }
    375 
    376 static void
    377 emit_resolve(struct radv_cmd_buffer *cmd_buffer,
    378 	     struct radv_image_view *src_iview,
    379 	     struct radv_image_view *dest_iview,
    380 	     const VkOffset2D *src_offset,
    381              const VkOffset2D *dest_offset,
    382              const VkExtent2D *resolve_extent)
    383 {
    384 	struct radv_device *device = cmd_buffer->device;
    385 	VkCommandBuffer cmd_buffer_h = radv_cmd_buffer_to_handle(cmd_buffer);
    386 	const uint32_t samples = src_iview->image->info.samples;
    387 	const uint32_t samples_log2 = ffs(samples) - 1;
    388 	radv_meta_push_descriptor_set(cmd_buffer,
    389 				      VK_PIPELINE_BIND_POINT_GRAPHICS,
    390 				      cmd_buffer->device->meta_state.resolve_fragment.p_layout,
    391 				      0, /* set */
    392 				      1, /* descriptorWriteCount */
    393 				      (VkWriteDescriptorSet[]) {
    394 					      {
    395 						      .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
    396 					              .dstBinding = 0,
    397 					              .dstArrayElement = 0,
    398 					              .descriptorCount = 1,
    399 					              .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
    400 						      .pImageInfo = (VkDescriptorImageInfo[]) {
    401 						      {
    402 						      .sampler = VK_NULL_HANDLE,
    403 						      .imageView = radv_image_view_to_handle(src_iview),
    404 						      .imageLayout = VK_IMAGE_LAYOUT_GENERAL,
    405 						      },
    406 						      }
    407 					      },
    408 				      });
    409 
    410 	cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_FLUSH_AND_INV_CB;
    411 
    412 	unsigned push_constants[2] = {
    413 		src_offset->x - dest_offset->x,
    414 		src_offset->y - dest_offset->y,
    415 	};
    416 	radv_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer),
    417 			      device->meta_state.resolve_fragment.p_layout,
    418 			      VK_SHADER_STAGE_FRAGMENT_BIT, 0, 8,
    419 			      push_constants);
    420 
    421 	unsigned fs_key = radv_format_meta_fs_key(dest_iview->vk_format);
    422 	VkPipeline pipeline_h = device->meta_state.resolve_fragment.rc[samples_log2].pipeline[fs_key];
    423 
    424 	radv_CmdBindPipeline(cmd_buffer_h, VK_PIPELINE_BIND_POINT_GRAPHICS,
    425 			     pipeline_h);
    426 
    427 	radv_CmdSetViewport(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1, &(VkViewport) {
    428 		.x = dest_offset->x,
    429 		.y = dest_offset->y,
    430 		.width = resolve_extent->width,
    431 		.height = resolve_extent->height,
    432 		.minDepth = 0.0f,
    433 		.maxDepth = 1.0f
    434 	});
    435 
    436 	radv_CmdSetScissor(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1, &(VkRect2D) {
    437 		.offset = *dest_offset,
    438 		.extent = *resolve_extent,
    439 	});
    440 
    441 	radv_CmdDraw(cmd_buffer_h, 3, 1, 0, 0);
    442 	cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_FLUSH_AND_INV_CB;
    443 }
    444 
    445 void radv_meta_resolve_fragment_image(struct radv_cmd_buffer *cmd_buffer,
    446 				      struct radv_image *src_image,
    447 				      VkImageLayout src_image_layout,
    448 				      struct radv_image *dest_image,
    449 				      VkImageLayout dest_image_layout,
    450 				      uint32_t region_count,
    451 				      const VkImageResolve *regions)
    452 {
    453 	struct radv_device *device = cmd_buffer->device;
    454 	struct radv_meta_saved_state saved_state;
    455 	const uint32_t samples = src_image->info.samples;
    456 	const uint32_t samples_log2 = ffs(samples) - 1;
    457 	unsigned fs_key = radv_format_meta_fs_key(dest_image->vk_format);
    458 	unsigned dst_layout = radv_meta_dst_layout_from_layout(dest_image_layout);
    459 	VkRenderPass rp;
    460 	for (uint32_t r = 0; r < region_count; ++r) {
    461 		const VkImageResolve *region = &regions[r];
    462 		const uint32_t src_base_layer =
    463 			radv_meta_get_iview_layer(src_image, &region->srcSubresource,
    464 						  &region->srcOffset);
    465 		VkImageSubresourceRange range;
    466 		range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
    467 		range.baseMipLevel = region->srcSubresource.mipLevel;
    468 		range.levelCount = 1;
    469 		range.baseArrayLayer = src_base_layer;
    470 		range.layerCount = region->srcSubresource.layerCount;
    471 		radv_fast_clear_flush_image_inplace(cmd_buffer, src_image, &range);
    472 	}
    473 
    474 	rp = device->meta_state.resolve_fragment.rc[samples_log2].render_pass[fs_key][dst_layout];
    475 
    476 	radv_meta_save(&saved_state, cmd_buffer,
    477 		       RADV_META_SAVE_GRAPHICS_PIPELINE |
    478 		       RADV_META_SAVE_CONSTANTS |
    479 		       RADV_META_SAVE_DESCRIPTORS);
    480 
    481 	for (uint32_t r = 0; r < region_count; ++r) {
    482 		const VkImageResolve *region = &regions[r];
    483 
    484 		assert(region->srcSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT);
    485 		assert(region->dstSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT);
    486 		assert(region->srcSubresource.layerCount == region->dstSubresource.layerCount);
    487 
    488 		const uint32_t src_base_layer =
    489 			radv_meta_get_iview_layer(src_image, &region->srcSubresource,
    490 						  &region->srcOffset);
    491 
    492 		const uint32_t dest_base_layer =
    493 			radv_meta_get_iview_layer(dest_image, &region->dstSubresource,
    494 						  &region->dstOffset);
    495 
    496 		const struct VkExtent3D extent =
    497 			radv_sanitize_image_extent(src_image->type, region->extent);
    498 		const struct VkOffset3D srcOffset =
    499 			radv_sanitize_image_offset(src_image->type, region->srcOffset);
    500 		const struct VkOffset3D dstOffset =
    501 			radv_sanitize_image_offset(dest_image->type, region->dstOffset);
    502 
    503 		for (uint32_t layer = 0; layer < region->srcSubresource.layerCount;
    504 		     ++layer) {
    505 
    506 			struct radv_image_view src_iview;
    507 			radv_image_view_init(&src_iview, cmd_buffer->device,
    508 					     &(VkImageViewCreateInfo) {
    509 						     .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
    510 							     .image = radv_image_to_handle(src_image),
    511 							     .viewType = radv_meta_get_view_type(src_image),
    512 							     .format = src_image->vk_format,
    513 							     .subresourceRange = {
    514 							     .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
    515 							     .baseMipLevel = region->srcSubresource.mipLevel,
    516 							     .levelCount = 1,
    517 							     .baseArrayLayer = src_base_layer + layer,
    518 							     .layerCount = 1,
    519 						     },
    520 					     });
    521 
    522 			struct radv_image_view dest_iview;
    523 			radv_image_view_init(&dest_iview, cmd_buffer->device,
    524 					     &(VkImageViewCreateInfo) {
    525 						     .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
    526 							     .image = radv_image_to_handle(dest_image),
    527 							     .viewType = radv_meta_get_view_type(dest_image),
    528 							     .format = dest_image->vk_format,
    529 							     .subresourceRange = {
    530 							     .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
    531 							     .baseMipLevel = region->dstSubresource.mipLevel,
    532 							     .levelCount = 1,
    533 							     .baseArrayLayer = dest_base_layer + layer,
    534 							     .layerCount = 1,
    535 						     },
    536 					     });
    537 
    538 
    539 			VkFramebuffer fb;
    540 			radv_CreateFramebuffer(radv_device_to_handle(cmd_buffer->device),
    541 			       &(VkFramebufferCreateInfo) {
    542 				       .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
    543 					       .attachmentCount = 1,
    544 					       .pAttachments = (VkImageView[]) {
    545 					       radv_image_view_to_handle(&dest_iview),
    546 				       },
    547 				       .width = extent.width + dstOffset.x,
    548 				       .height = extent.height + dstOffset.y,
    549 				       .layers = 1
    550 				}, &cmd_buffer->pool->alloc, &fb);
    551 
    552 			radv_CmdBeginRenderPass(radv_cmd_buffer_to_handle(cmd_buffer),
    553 						&(VkRenderPassBeginInfo) {
    554 							.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
    555 								.renderPass = rp,
    556 								.framebuffer = fb,
    557 								.renderArea = {
    558 								.offset = { dstOffset.x, dstOffset.y, },
    559 								.extent = { extent.width, extent.height },
    560 							},
    561 								.clearValueCount = 0,
    562 								.pClearValues = NULL,
    563 						}, VK_SUBPASS_CONTENTS_INLINE);
    564 
    565 
    566 
    567 			emit_resolve(cmd_buffer,
    568 				     &src_iview,
    569 				     &dest_iview,
    570 				     &(VkOffset2D) { srcOffset.x, srcOffset.y },
    571 				     &(VkOffset2D) { dstOffset.x, dstOffset.y },
    572 				     &(VkExtent2D) { extent.width, extent.height });
    573 
    574 			radv_CmdEndRenderPass(radv_cmd_buffer_to_handle(cmd_buffer));
    575 
    576 			radv_DestroyFramebuffer(radv_device_to_handle(cmd_buffer->device), fb, &cmd_buffer->pool->alloc);
    577 		}
    578 	}
    579 
    580 	radv_meta_restore(&saved_state, cmd_buffer);
    581 }
    582 
    583 
    584 /**
    585  * Emit any needed resolves for the current subpass.
    586  */
    587 void
    588 radv_cmd_buffer_resolve_subpass_fs(struct radv_cmd_buffer *cmd_buffer)
    589 {
    590 	struct radv_framebuffer *fb = cmd_buffer->state.framebuffer;
    591 	const struct radv_subpass *subpass = cmd_buffer->state.subpass;
    592 	struct radv_meta_saved_state saved_state;
    593 
    594 	/* FINISHME(perf): Skip clears for resolve attachments.
    595 	 *
    596 	 * From the Vulkan 1.0 spec:
    597 	 *
    598 	 *    If the first use of an attachment in a render pass is as a resolve
    599 	 *    attachment, then the loadOp is effectively ignored as the resolve is
    600 	 *    guaranteed to overwrite all pixels in the render area.
    601 	 */
    602 
    603 	if (!subpass->has_resolve)
    604 		return;
    605 
    606 	radv_meta_save(&saved_state, cmd_buffer,
    607 		       RADV_META_SAVE_GRAPHICS_PIPELINE |
    608 		       RADV_META_SAVE_CONSTANTS |
    609 		       RADV_META_SAVE_DESCRIPTORS);
    610 
    611 	/* Resolves happen before the end-of-subpass barriers get executed,
    612 	 * so we have to make the attachment shader-readable */
    613 	cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_PS_PARTIAL_FLUSH |
    614 	                                RADV_CMD_FLAG_FLUSH_AND_INV_CB |
    615 	                                RADV_CMD_FLAG_FLUSH_AND_INV_CB_META |
    616 	                                RADV_CMD_FLAG_FLUSH_AND_INV_DB |
    617 	                                RADV_CMD_FLAG_FLUSH_AND_INV_DB_META |
    618 	                                RADV_CMD_FLAG_INV_GLOBAL_L2 |
    619 	                                RADV_CMD_FLAG_INV_VMEM_L1;
    620 
    621 	for (uint32_t i = 0; i < subpass->color_count; ++i) {
    622 		VkAttachmentReference src_att = subpass->color_attachments[i];
    623 		VkAttachmentReference dest_att = subpass->resolve_attachments[i];
    624 
    625 		if (src_att.attachment == VK_ATTACHMENT_UNUSED ||
    626 		    dest_att.attachment == VK_ATTACHMENT_UNUSED)
    627 			continue;
    628 
    629 		struct radv_image_view *dest_iview = cmd_buffer->state.framebuffer->attachments[dest_att.attachment].attachment;
    630 		struct radv_image_view *src_iview = cmd_buffer->state.framebuffer->attachments[src_att.attachment].attachment;
    631 
    632 		{
    633 			VkImageSubresourceRange range;
    634 			range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
    635 			range.baseMipLevel = 0;
    636 			range.levelCount = 1;
    637 			range.baseArrayLayer = 0;
    638 			range.layerCount = 1;
    639 			radv_fast_clear_flush_image_inplace(cmd_buffer, src_iview->image, &range);
    640 		}
    641 
    642 		struct radv_subpass resolve_subpass = {
    643 			.color_count = 1,
    644 			.color_attachments = (VkAttachmentReference[]) { dest_att },
    645 			.depth_stencil_attachment = { .attachment = VK_ATTACHMENT_UNUSED },
    646 		};
    647 
    648 		radv_cmd_buffer_set_subpass(cmd_buffer, &resolve_subpass, false);
    649 
    650 		emit_resolve(cmd_buffer,
    651 			     src_iview,
    652 			     dest_iview,
    653 			     &(VkOffset2D) { 0, 0 },
    654 			     &(VkOffset2D) { 0, 0 },
    655 			     &(VkExtent2D) { fb->width, fb->height });
    656 	}
    657 
    658 	cmd_buffer->state.subpass = subpass;
    659 	radv_meta_restore(&saved_state, cmd_buffer);
    660 }
    661