[v2] radv: fix multisample image copies

Submitted by Samuel Pitoiset on April 27, 2018, 11:23 a.m.

Details

Message ID 20180427112351.5713-1-samuel.pitoiset@gmail.com
State New
Headers show
Series "radv: fix multisample image copies" ( rev: 2 ) in Mesa

Not browsing as part of any series.

Commit Message

Samuel Pitoiset April 27, 2018, 11:23 a.m.
From: Matthew Nicholls <mnicholls@feralinteractive.com>

Previously before fb077b0728, the LOD parameter was being used in place of the
sample index, which would only copy the first sample to all samples in the
destination image. After that multisample image copies wouldn't copy anything
from my observations.

This fixes some copy_and_blit CTS tests.

v2: - use GLSL_SAMPLER_DIM_MS instead of 2D (Samuel)
    - updated commit description (Samuel)

Fix this properly by copying each sample in a separate radv_CmdDraw and using a
pipeline with the correct rasterizationSamples for the destination image.

Cc: 18.0 18.1 <mesa-stable@lists.freedesktop.org>
---
 src/amd/vulkan/radv_meta_blit2d.c | 282 +++++++++++++++++++-----------
 src/amd/vulkan/radv_private.h     |  18 +-
 2 files changed, 191 insertions(+), 109 deletions(-)

Patch hide | download patch | download mbox

diff --git a/src/amd/vulkan/radv_meta_blit2d.c b/src/amd/vulkan/radv_meta_blit2d.c
index e163056257e..3ad032f5989 100644
--- a/src/amd/vulkan/radv_meta_blit2d.c
+++ b/src/amd/vulkan/radv_meta_blit2d.c
@@ -100,7 +100,8 @@  blit2d_bind_src(struct radv_cmd_buffer *cmd_buffer,
                 struct radv_meta_blit2d_buffer *src_buf,
                 struct blit2d_src_temps *tmp,
                 enum blit2d_src_type src_type, VkFormat depth_format,
-                VkImageAspectFlagBits aspects)
+                VkImageAspectFlagBits aspects,
+                uint32_t log2_samples)
 {
 	struct radv_device *device = cmd_buffer->device;
 
@@ -108,7 +109,7 @@  blit2d_bind_src(struct radv_cmd_buffer *cmd_buffer,
 		create_bview(cmd_buffer, src_buf, &tmp->bview, depth_format);
 
 		radv_meta_push_descriptor_set(cmd_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
-					      device->meta_state.blit2d.p_layouts[src_type],
+					      device->meta_state.blit2d[log2_samples].p_layouts[src_type],
 					      0, /* set */
 					      1, /* descriptorWriteCount */
 					      (VkWriteDescriptorSet[]) {
@@ -123,7 +124,7 @@  blit2d_bind_src(struct radv_cmd_buffer *cmd_buffer,
 					      });
 
 		radv_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer),
-				      device->meta_state.blit2d.p_layouts[src_type],
+				      device->meta_state.blit2d[log2_samples].p_layouts[src_type],
 				      VK_SHADER_STAGE_FRAGMENT_BIT, 16, 4,
 				      &src_buf->pitch);
 	} else {
@@ -131,12 +132,12 @@  blit2d_bind_src(struct radv_cmd_buffer *cmd_buffer,
 
 		if (src_type == BLIT2D_SRC_TYPE_IMAGE_3D)
 			radv_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer),
-					      device->meta_state.blit2d.p_layouts[src_type],
+					      device->meta_state.blit2d[log2_samples].p_layouts[src_type],
 					      VK_SHADER_STAGE_FRAGMENT_BIT, 16, 4,
 					      &src_img->layer);
 
 		radv_meta_push_descriptor_set(cmd_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
-					      device->meta_state.blit2d.p_layouts[src_type],
+					      device->meta_state.blit2d[log2_samples].p_layouts[src_type],
 					      0, /* set */
 					      1, /* descriptorWriteCount */
 					      (VkWriteDescriptorSet[]) {
@@ -190,10 +191,11 @@  blit2d_bind_dst(struct radv_cmd_buffer *cmd_buffer,
 
 static void
 bind_pipeline(struct radv_cmd_buffer *cmd_buffer,
-              enum blit2d_src_type src_type, unsigned fs_key)
+              enum blit2d_src_type src_type, unsigned fs_key,
+              uint32_t log2_samples)
 {
 	VkPipeline pipeline =
-		cmd_buffer->device->meta_state.blit2d.pipelines[src_type][fs_key];
+		cmd_buffer->device->meta_state.blit2d[log2_samples].pipelines[src_type][fs_key];
 
 	radv_CmdBindPipeline(radv_cmd_buffer_to_handle(cmd_buffer),
 			     VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
@@ -201,10 +203,11 @@  bind_pipeline(struct radv_cmd_buffer *cmd_buffer,
 
 static void
 bind_depth_pipeline(struct radv_cmd_buffer *cmd_buffer,
-		    enum blit2d_src_type src_type)
+		    enum blit2d_src_type src_type,
+		    uint32_t log2_samples)
 {
 	VkPipeline pipeline =
-		cmd_buffer->device->meta_state.blit2d.depth_only_pipeline[src_type];
+		cmd_buffer->device->meta_state.blit2d[log2_samples].depth_only_pipeline[src_type];
 
 	radv_CmdBindPipeline(radv_cmd_buffer_to_handle(cmd_buffer),
 			     VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
@@ -212,10 +215,11 @@  bind_depth_pipeline(struct radv_cmd_buffer *cmd_buffer,
 
 static void
 bind_stencil_pipeline(struct radv_cmd_buffer *cmd_buffer,
-		      enum blit2d_src_type src_type)
+		      enum blit2d_src_type src_type,
+		      uint32_t log2_samples)
 {
 	VkPipeline pipeline =
-		cmd_buffer->device->meta_state.blit2d.stencil_only_pipeline[src_type];
+		cmd_buffer->device->meta_state.blit2d[log2_samples].stencil_only_pipeline[src_type];
 
 	radv_CmdBindPipeline(radv_cmd_buffer_to_handle(cmd_buffer),
 			     VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
@@ -227,7 +231,8 @@  radv_meta_blit2d_normal_dst(struct radv_cmd_buffer *cmd_buffer,
 			    struct radv_meta_blit2d_buffer *src_buf,
 			    struct radv_meta_blit2d_surf *dst,
 			    unsigned num_rects,
-			    struct radv_meta_blit2d_rect *rects, enum blit2d_src_type src_type)
+			    struct radv_meta_blit2d_rect *rects, enum blit2d_src_type src_type,
+			    uint32_t log2_samples)
 {
 	struct radv_device *device = cmd_buffer->device;
 
@@ -241,7 +246,7 @@  radv_meta_blit2d_normal_dst(struct radv_cmd_buffer *cmd_buffer,
 			else if (aspect_mask == VK_IMAGE_ASPECT_DEPTH_BIT)
 				depth_format = vk_format_depth_only(dst->image->vk_format);
 			struct blit2d_src_temps src_temps;
-			blit2d_bind_src(cmd_buffer, src_img, src_buf, &src_temps, src_type, depth_format, aspect_mask);
+			blit2d_bind_src(cmd_buffer, src_img, src_buf, &src_temps, src_type, depth_format, aspect_mask, log2_samples);
 
 			struct blit2d_dst_temps dst_temps;
 			blit2d_bind_dst(cmd_buffer, dst, rects[r].dst_x + rects[r].width,
@@ -255,7 +260,7 @@  radv_meta_blit2d_normal_dst(struct radv_cmd_buffer *cmd_buffer,
 			};
 
 			radv_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer),
-					device->meta_state.blit2d.p_layouts[src_type],
+					device->meta_state.blit2d[log2_samples].p_layouts[src_type],
 					VK_SHADER_STAGE_VERTEX_BIT, 0, 16,
 					vertex_push_constants);
 
@@ -266,7 +271,7 @@  radv_meta_blit2d_normal_dst(struct radv_cmd_buffer *cmd_buffer,
 				radv_CmdBeginRenderPass(radv_cmd_buffer_to_handle(cmd_buffer),
 							&(VkRenderPassBeginInfo) {
 								.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
-									.renderPass = device->meta_state.blit2d.render_passes[fs_key][dst_layout],
+									.renderPass = device->meta_state.blit2d_render_passes[fs_key][dst_layout],
 									.framebuffer = dst_temps.fb,
 									.renderArea = {
 									.offset = { rects[r].dst_x, rects[r].dst_y, },
@@ -277,13 +282,13 @@  radv_meta_blit2d_normal_dst(struct radv_cmd_buffer *cmd_buffer,
 										}, VK_SUBPASS_CONTENTS_INLINE);
 
 
-				bind_pipeline(cmd_buffer, src_type, fs_key);
+				bind_pipeline(cmd_buffer, src_type, fs_key, log2_samples);
 			} else if (aspect_mask == VK_IMAGE_ASPECT_DEPTH_BIT) {
 				enum radv_blit_ds_layout ds_layout = radv_meta_blit_ds_to_type(dst->current_layout);
 				radv_CmdBeginRenderPass(radv_cmd_buffer_to_handle(cmd_buffer),
 							&(VkRenderPassBeginInfo) {
 								.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
-									.renderPass = device->meta_state.blit2d.depth_only_rp[ds_layout],
+									.renderPass = device->meta_state.blit2d_depth_only_rp[ds_layout],
 									.framebuffer = dst_temps.fb,
 									.renderArea = {
 									.offset = { rects[r].dst_x, rects[r].dst_y, },
@@ -294,14 +299,14 @@  radv_meta_blit2d_normal_dst(struct radv_cmd_buffer *cmd_buffer,
 										}, VK_SUBPASS_CONTENTS_INLINE);
 
 
-				bind_depth_pipeline(cmd_buffer, src_type);
+				bind_depth_pipeline(cmd_buffer, src_type, log2_samples);
 
 			} else if (aspect_mask == VK_IMAGE_ASPECT_STENCIL_BIT) {
 				enum radv_blit_ds_layout ds_layout = radv_meta_blit_ds_to_type(dst->current_layout);
 				radv_CmdBeginRenderPass(radv_cmd_buffer_to_handle(cmd_buffer),
 							&(VkRenderPassBeginInfo) {
 								.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
-									.renderPass = device->meta_state.blit2d.stencil_only_rp[ds_layout],
+									.renderPass = device->meta_state.blit2d_stencil_only_rp[ds_layout],
 									.framebuffer = dst_temps.fb,
 									.renderArea = {
 									.offset = { rects[r].dst_x, rects[r].dst_y, },
@@ -312,7 +317,7 @@  radv_meta_blit2d_normal_dst(struct radv_cmd_buffer *cmd_buffer,
 										}, VK_SUBPASS_CONTENTS_INLINE);
 
 
-				bind_stencil_pipeline(cmd_buffer, src_type);
+				bind_stencil_pipeline(cmd_buffer, src_type, log2_samples);
 			} else
 				unreachable("Processing blit2d with multiple aspects.");
 
@@ -332,7 +337,24 @@  radv_meta_blit2d_normal_dst(struct radv_cmd_buffer *cmd_buffer,
 
 
 
-			radv_CmdDraw(radv_cmd_buffer_to_handle(cmd_buffer), 3, 1, 0, 0);
+			if (log2_samples > 0) {
+				for (uint32_t sample = 0; sample < src_img->image->info.samples; sample++) {
+					uint32_t sample_mask = 1 << sample;
+					radv_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer),
+							      device->meta_state.blit2d[log2_samples].p_layouts[src_type],
+							      VK_SHADER_STAGE_FRAGMENT_BIT, 20, 4,
+							      &sample);
+
+					radv_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer),
+							      device->meta_state.blit2d[log2_samples].p_layouts[src_type],
+							      VK_SHADER_STAGE_FRAGMENT_BIT, 24, 4,
+							      &sample_mask);
+
+					radv_CmdDraw(radv_cmd_buffer_to_handle(cmd_buffer), 3, 1, 0, 0);
+				}
+			}
+			else
+				radv_CmdDraw(radv_cmd_buffer_to_handle(cmd_buffer), 3, 1, 0, 0);
 			radv_CmdEndRenderPass(radv_cmd_buffer_to_handle(cmd_buffer));
 
 			/* At the point where we emit the draw call, all data from the
@@ -358,7 +380,8 @@  radv_meta_blit2d(struct radv_cmd_buffer *cmd_buffer,
 	enum blit2d_src_type src_type = src_buf ? BLIT2D_SRC_TYPE_BUFFER :
 		use_3d ? BLIT2D_SRC_TYPE_IMAGE_3D : BLIT2D_SRC_TYPE_IMAGE;
 	radv_meta_blit2d_normal_dst(cmd_buffer, src_img, src_buf, dst,
-				    num_rects, rects, src_type);
+				    num_rects, rects, src_type,
+				    src_img ? util_logbase2(src_img->image->info.samples) : 0);
 }
 
 static nir_shader *
@@ -421,13 +444,14 @@  build_nir_vertex_shader(void)
 
 typedef nir_ssa_def* (*texel_fetch_build_func)(struct nir_builder *,
                                                struct radv_device *,
-                                               nir_ssa_def *, bool);
+                                               nir_ssa_def *, bool, bool);
 
 static nir_ssa_def *
 build_nir_texel_fetch(struct nir_builder *b, struct radv_device *device,
-                      nir_ssa_def *tex_pos, bool is_3d)
+                      nir_ssa_def *tex_pos, bool is_3d, bool is_multisampled)
 {
-	enum glsl_sampler_dim dim = is_3d ? GLSL_SAMPLER_DIM_3D : GLSL_SAMPLER_DIM_2D;
+	enum glsl_sampler_dim dim =
+		is_3d ? GLSL_SAMPLER_DIM_3D : is_multisampled ? GLSL_SAMPLER_DIM_MS : GLSL_SAMPLER_DIM_2D;
 	const struct glsl_type *sampler_type =
 		glsl_sampler_type(dim, false, false, GLSL_TYPE_UINT);
 	nir_variable *sampler = nir_variable_create(b->shader, nir_var_uniform,
@@ -436,6 +460,7 @@  build_nir_texel_fetch(struct nir_builder *b, struct radv_device *device,
 	sampler->data.binding = 0;
 
 	nir_ssa_def *tex_pos_3d = NULL;
+	nir_intrinsic_instr *sample_idx = NULL;
 	if (is_3d) {
 		nir_intrinsic_instr *layer = nir_intrinsic_instr_create(b->shader, nir_intrinsic_load_push_constant);
 		nir_intrinsic_set_base(layer, 16);
@@ -451,13 +476,22 @@  build_nir_texel_fetch(struct nir_builder *b, struct radv_device *device,
 		chans[2] = &layer->dest.ssa;
 		tex_pos_3d = nir_vec(b, chans, 3);
 	}
+	if (is_multisampled) {
+		sample_idx = nir_intrinsic_instr_create(b->shader, nir_intrinsic_load_push_constant);
+		nir_intrinsic_set_base(sample_idx, 20);
+		nir_intrinsic_set_range(sample_idx, 4);
+		sample_idx->src[0] = nir_src_for_ssa(nir_imm_int(b, 0));
+		sample_idx->num_components = 1;
+		nir_ssa_dest_init(&sample_idx->instr, &sample_idx->dest, 1, 32, "sample_idx");
+		nir_builder_instr_insert(b, &sample_idx->instr);
+	}
 	nir_tex_instr *tex = nir_tex_instr_create(b->shader, 2);
 	tex->sampler_dim = dim;
-	tex->op = nir_texop_txf;
+	tex->op = is_multisampled ? nir_texop_txf_ms : nir_texop_txf;
 	tex->src[0].src_type = nir_tex_src_coord;
 	tex->src[0].src = nir_src_for_ssa(is_3d ? tex_pos_3d : tex_pos);
-	tex->src[1].src_type = nir_tex_src_lod;
-	tex->src[1].src = nir_src_for_ssa(nir_imm_int(b, 0));
+	tex->src[1].src_type = is_multisampled ? nir_tex_src_ms_index : nir_tex_src_lod;
+	tex->src[1].src = nir_src_for_ssa(is_multisampled ? &sample_idx->dest.ssa : nir_imm_int(b, 0));
 	tex->dest_type = nir_type_uint;
 	tex->is_array = false;
 	tex->coord_components = is_3d ? 3 : 2;
@@ -473,7 +507,7 @@  build_nir_texel_fetch(struct nir_builder *b, struct radv_device *device,
 
 static nir_ssa_def *
 build_nir_buffer_fetch(struct nir_builder *b, struct radv_device *device,
-		       nir_ssa_def *tex_pos, bool is_3d)
+		       nir_ssa_def *tex_pos, bool is_3d, bool is_multisampled)
 {
 	const struct glsl_type *sampler_type =
 		glsl_sampler_type(GLSL_SAMPLER_DIM_BUF, false, false, GLSL_TYPE_UINT);
@@ -519,9 +553,31 @@  static const VkPipelineVertexInputStateCreateInfo normal_vi_create_info = {
 	.vertexAttributeDescriptionCount = 0,
 };
 
+static void
+build_nir_store_sample_mask(struct nir_builder *b)
+{
+	nir_intrinsic_instr *sample_mask = nir_intrinsic_instr_create(b->shader, nir_intrinsic_load_push_constant);
+	nir_intrinsic_set_base(sample_mask, 24);
+	nir_intrinsic_set_range(sample_mask, 4);
+	sample_mask->src[0] = nir_src_for_ssa(nir_imm_int(b, 0));
+	sample_mask->num_components = 1;
+	nir_ssa_dest_init(&sample_mask->instr, &sample_mask->dest, 1, 32, "sample_mask");
+	nir_builder_instr_insert(b, &sample_mask->instr);
+
+	const struct glsl_type *sample_mask_out_type = glsl_uint_type();
+
+	nir_variable *sample_mask_out =
+		nir_variable_create(b->shader, nir_var_shader_out,
+				    sample_mask_out_type, "sample_mask_out");
+	sample_mask_out->data.location = FRAG_RESULT_SAMPLE_MASK;
+
+	nir_store_var(b, sample_mask_out, &sample_mask->dest.ssa, 0x1);
+}
+
 static nir_shader *
 build_nir_copy_fragment_shader(struct radv_device *device,
-                               texel_fetch_build_func txf_func, const char* name, bool is_3d)
+                               texel_fetch_build_func txf_func, const char* name, bool is_3d,
+                               bool is_multisampled)
 {
 	const struct glsl_type *vec4 = glsl_vec4_type();
 	const struct glsl_type *vec2 = glsl_vector_type(GLSL_TYPE_FLOAT, 2);
@@ -538,11 +594,15 @@  build_nir_copy_fragment_shader(struct radv_device *device,
 						      vec4, "f_color");
 	color_out->data.location = FRAG_RESULT_DATA0;
 
+	if (is_multisampled) {
+		build_nir_store_sample_mask(&b);
+	}
+
 	nir_ssa_def *pos_int = nir_f2i32(&b, nir_load_var(&b, tex_pos_in));
 	unsigned swiz[4] = { 0, 1 };
 	nir_ssa_def *tex_pos = nir_swizzle(&b, pos_int, swiz, 2, false);
 
-	nir_ssa_def *color = txf_func(&b, device, tex_pos, is_3d);
+	nir_ssa_def *color = txf_func(&b, device, tex_pos, is_3d, is_multisampled);
 	nir_store_var(&b, color_out, color, 0xf);
 
 	return b.shader;
@@ -550,7 +610,8 @@  build_nir_copy_fragment_shader(struct radv_device *device,
 
 static nir_shader *
 build_nir_copy_fragment_shader_depth(struct radv_device *device,
-				     texel_fetch_build_func txf_func, const char* name, bool is_3d)
+				     texel_fetch_build_func txf_func, const char* name, bool is_3d,
+				     bool is_multisampled)
 {
 	const struct glsl_type *vec4 = glsl_vec4_type();
 	const struct glsl_type *vec2 = glsl_vector_type(GLSL_TYPE_FLOAT, 2);
@@ -567,11 +628,15 @@  build_nir_copy_fragment_shader_depth(struct radv_device *device,
 						      vec4, "f_color");
 	color_out->data.location = FRAG_RESULT_DEPTH;
 
+	if (is_multisampled) {
+		build_nir_store_sample_mask(&b);
+	}
+
 	nir_ssa_def *pos_int = nir_f2i32(&b, nir_load_var(&b, tex_pos_in));
 	unsigned swiz[4] = { 0, 1 };
 	nir_ssa_def *tex_pos = nir_swizzle(&b, pos_int, swiz, 2, false);
 
-	nir_ssa_def *color = txf_func(&b, device, tex_pos, is_3d);
+	nir_ssa_def *color = txf_func(&b, device, tex_pos, is_3d, is_multisampled);
 	nir_store_var(&b, color_out, color, 0x1);
 
 	return b.shader;
@@ -579,7 +644,8 @@  build_nir_copy_fragment_shader_depth(struct radv_device *device,
 
 static nir_shader *
 build_nir_copy_fragment_shader_stencil(struct radv_device *device,
-				       texel_fetch_build_func txf_func, const char* name, bool is_3d)
+				       texel_fetch_build_func txf_func, const char* name, bool is_3d,
+				       bool is_multisampled)
 {
 	const struct glsl_type *vec4 = glsl_vec4_type();
 	const struct glsl_type *vec2 = glsl_vector_type(GLSL_TYPE_FLOAT, 2);
@@ -596,11 +662,15 @@  build_nir_copy_fragment_shader_stencil(struct radv_device *device,
 						      vec4, "f_color");
 	color_out->data.location = FRAG_RESULT_STENCIL;
 
+	if (is_multisampled) {
+		build_nir_store_sample_mask(&b);
+	}
+
 	nir_ssa_def *pos_int = nir_f2i32(&b, nir_load_var(&b, tex_pos_in));
 	unsigned swiz[4] = { 0, 1 };
 	nir_ssa_def *tex_pos = nir_swizzle(&b, pos_int, swiz, 2, false);
 
-	nir_ssa_def *color = txf_func(&b, device, tex_pos, is_3d);
+	nir_ssa_def *color = txf_func(&b, device, tex_pos, is_3d, is_multisampled);
 	nir_store_var(&b, color_out, color, 0x1);
 
 	return b.shader;
@@ -614,45 +684,48 @@  radv_device_finish_meta_blit2d_state(struct radv_device *device)
 	for(unsigned j = 0; j < NUM_META_FS_KEYS; ++j) {
 		for (unsigned k = 0; k < RADV_META_DST_LAYOUT_COUNT; ++k) {
 			radv_DestroyRenderPass(radv_device_to_handle(device),
-			                       state->blit2d.render_passes[j][k],
-			                       &state->alloc);
+					       state->blit2d_render_passes[j][k],
+					       &state->alloc);
 		}
 	}
 
 	for (enum radv_blit_ds_layout j = RADV_BLIT_DS_LAYOUT_TILE_ENABLE; j < RADV_BLIT_DS_LAYOUT_COUNT; j++) {
 		radv_DestroyRenderPass(radv_device_to_handle(device),
-				       state->blit2d.depth_only_rp[j], &state->alloc);
+				       state->blit2d_depth_only_rp[j], &state->alloc);
 		radv_DestroyRenderPass(radv_device_to_handle(device),
-				       state->blit2d.stencil_only_rp[j], &state->alloc);
+				       state->blit2d_stencil_only_rp[j], &state->alloc);
 	}
 
-	for (unsigned src = 0; src < BLIT2D_NUM_SRC_TYPES; src++) {
-		radv_DestroyPipelineLayout(radv_device_to_handle(device),
-					   state->blit2d.p_layouts[src],
-					   &state->alloc);
-		radv_DestroyDescriptorSetLayout(radv_device_to_handle(device),
-						state->blit2d.ds_layouts[src],
-						&state->alloc);
+	for (unsigned log2_samples = 0; log2_samples < 1 + MAX_SAMPLES_LOG2; ++log2_samples) {
+		for (unsigned src = 0; src < BLIT2D_NUM_SRC_TYPES; src++) {
+			radv_DestroyPipelineLayout(radv_device_to_handle(device),
+						   state->blit2d[log2_samples].p_layouts[src],
+						   &state->alloc);
+			radv_DestroyDescriptorSetLayout(radv_device_to_handle(device),
+							state->blit2d[log2_samples].ds_layouts[src],
+							&state->alloc);
+
+			for (unsigned j = 0; j < NUM_META_FS_KEYS; ++j) {
+				radv_DestroyPipeline(radv_device_to_handle(device),
+						     state->blit2d[log2_samples].pipelines[src][j],
+						     &state->alloc);
+			}
 
-		for (unsigned j = 0; j < NUM_META_FS_KEYS; ++j) {
 			radv_DestroyPipeline(radv_device_to_handle(device),
-					     state->blit2d.pipelines[src][j],
+					     state->blit2d[log2_samples].depth_only_pipeline[src],
+					     &state->alloc);
+			radv_DestroyPipeline(radv_device_to_handle(device),
+					     state->blit2d[log2_samples].stencil_only_pipeline[src],
 					     &state->alloc);
 		}
-
-		radv_DestroyPipeline(radv_device_to_handle(device),
-				     state->blit2d.depth_only_pipeline[src],
-				     &state->alloc);
-		radv_DestroyPipeline(radv_device_to_handle(device),
-				     state->blit2d.stencil_only_pipeline[src],
-				     &state->alloc);
 	}
 }
 
 static VkResult
 blit2d_init_color_pipeline(struct radv_device *device,
 			   enum blit2d_src_type src_type,
-			   VkFormat format)
+			   VkFormat format,
+			   uint32_t log2_samples)
 {
 	VkResult result;
 	unsigned fs_key = radv_format_meta_fs_key(format);
@@ -681,7 +754,7 @@  blit2d_init_color_pipeline(struct radv_device *device,
 	struct radv_shader_module fs = { .nir = NULL };
 
 
-	fs.nir = build_nir_copy_fragment_shader(device, src_func, name, src_type == BLIT2D_SRC_TYPE_IMAGE_3D);
+	fs.nir = build_nir_copy_fragment_shader(device, src_func, name, src_type == BLIT2D_SRC_TYPE_IMAGE_3D, log2_samples > 0);
 	vi_create_info = &normal_vi_create_info;
 
 	struct radv_shader_module vs = {
@@ -705,7 +778,7 @@  blit2d_init_color_pipeline(struct radv_device *device,
 	};
 
 	for (unsigned dst_layout = 0; dst_layout < RADV_META_DST_LAYOUT_COUNT; ++dst_layout) {
-		if (!device->meta_state.blit2d.render_passes[fs_key][dst_layout]) {
+		if (!device->meta_state.blit2d_render_passes[fs_key][dst_layout]) {
 			VkImageLayout layout = radv_meta_dst_layout_to_layout(dst_layout);
 
 			result = radv_CreateRenderPass(radv_device_to_handle(device),
@@ -737,7 +810,7 @@  blit2d_init_color_pipeline(struct radv_device *device,
 						.pPreserveAttachments = (uint32_t[]) { 0 },
 						},
 						.dependencyCount = 0,
-					}, &device->meta_state.alloc, &device->meta_state.blit2d.render_passes[fs_key][dst_layout]);
+					}, &device->meta_state.alloc, &device->meta_state.blit2d_render_passes[fs_key][dst_layout]);
 		}
 	}
 
@@ -765,7 +838,7 @@  blit2d_init_color_pipeline(struct radv_device *device,
 		},
 		.pMultisampleState = &(VkPipelineMultisampleStateCreateInfo) {
 			.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
-			.rasterizationSamples = 1,
+			.rasterizationSamples = 1 << log2_samples,
 			.sampleShadingEnable = false,
 			.pSampleMask = (VkSampleMask[]) { UINT32_MAX },
 		},
@@ -796,8 +869,8 @@  blit2d_init_color_pipeline(struct radv_device *device,
 			},
 		},
 		.flags = 0,
-		.layout = device->meta_state.blit2d.p_layouts[src_type],
-		.renderPass = device->meta_state.blit2d.render_passes[fs_key][0],
+		.layout = device->meta_state.blit2d[log2_samples].p_layouts[src_type],
+		.renderPass = device->meta_state.blit2d_render_passes[fs_key][0],
 		.subpass = 0,
 	};
 
@@ -809,7 +882,7 @@  blit2d_init_color_pipeline(struct radv_device *device,
 					       radv_pipeline_cache_to_handle(&device->meta_state.cache),
 					       &vk_pipeline_info, &radv_pipeline_info,
 					       &device->meta_state.alloc,
-					       &device->meta_state.blit2d.pipelines[src_type][fs_key]);
+					       &device->meta_state.blit2d[log2_samples].pipelines[src_type][fs_key]);
 
 
 	ralloc_free(vs.nir);
@@ -820,7 +893,8 @@  blit2d_init_color_pipeline(struct radv_device *device,
 
 static VkResult
 blit2d_init_depth_only_pipeline(struct radv_device *device,
-				enum blit2d_src_type src_type)
+				enum blit2d_src_type src_type,
+				uint32_t log2_samples)
 {
 	VkResult result;
 	const char *name;
@@ -847,7 +921,7 @@  blit2d_init_depth_only_pipeline(struct radv_device *device,
 	const VkPipelineVertexInputStateCreateInfo *vi_create_info;
 	struct radv_shader_module fs = { .nir = NULL };
 
-	fs.nir = build_nir_copy_fragment_shader_depth(device, src_func, name, src_type == BLIT2D_SRC_TYPE_IMAGE_3D);
+	fs.nir = build_nir_copy_fragment_shader_depth(device, src_func, name, src_type == BLIT2D_SRC_TYPE_IMAGE_3D, log2_samples > 0);
 	vi_create_info = &normal_vi_create_info;
 
 	struct radv_shader_module vs = {
@@ -871,7 +945,7 @@  blit2d_init_depth_only_pipeline(struct radv_device *device,
 	};
 
 	for (enum radv_blit_ds_layout ds_layout = RADV_BLIT_DS_LAYOUT_TILE_ENABLE; ds_layout < RADV_BLIT_DS_LAYOUT_COUNT; ds_layout++) {
-		if (!device->meta_state.blit2d.depth_only_rp[ds_layout]) {
+		if (!device->meta_state.blit2d_depth_only_rp[ds_layout]) {
 			VkImageLayout layout = radv_meta_blit_ds_to_layout(ds_layout);
 			result = radv_CreateRenderPass(radv_device_to_handle(device),
 						       &(VkRenderPassCreateInfo) {
@@ -899,7 +973,7 @@  blit2d_init_depth_only_pipeline(struct radv_device *device,
 								       .pPreserveAttachments = (uint32_t[]) { 0 },
 							       },
 							       .dependencyCount = 0,
-							}, &device->meta_state.alloc, &device->meta_state.blit2d.depth_only_rp[ds_layout]);
+							}, &device->meta_state.alloc, &device->meta_state.blit2d_depth_only_rp[ds_layout]);
 		}
 	}
 
@@ -927,7 +1001,7 @@  blit2d_init_depth_only_pipeline(struct radv_device *device,
 		},
 		.pMultisampleState = &(VkPipelineMultisampleStateCreateInfo) {
 			.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
-			.rasterizationSamples = 1,
+			.rasterizationSamples = 1 << log2_samples,
 			.sampleShadingEnable = false,
 			.pSampleMask = (VkSampleMask[]) { UINT32_MAX },
 		},
@@ -958,8 +1032,8 @@  blit2d_init_depth_only_pipeline(struct radv_device *device,
 			},
 		},
 		.flags = 0,
-		.layout = device->meta_state.blit2d.p_layouts[src_type],
-		.renderPass = device->meta_state.blit2d.depth_only_rp[0],
+		.layout = device->meta_state.blit2d[log2_samples].p_layouts[src_type],
+		.renderPass = device->meta_state.blit2d_depth_only_rp[0],
 		.subpass = 0,
 	};
 
@@ -971,7 +1045,7 @@  blit2d_init_depth_only_pipeline(struct radv_device *device,
 					       radv_pipeline_cache_to_handle(&device->meta_state.cache),
 					       &vk_pipeline_info, &radv_pipeline_info,
 					       &device->meta_state.alloc,
-					       &device->meta_state.blit2d.depth_only_pipeline[src_type]);
+					       &device->meta_state.blit2d[log2_samples].depth_only_pipeline[src_type]);
 
 
 	ralloc_free(vs.nir);
@@ -982,7 +1056,8 @@  blit2d_init_depth_only_pipeline(struct radv_device *device,
 
 static VkResult
 blit2d_init_stencil_only_pipeline(struct radv_device *device,
-				  enum blit2d_src_type src_type)
+				  enum blit2d_src_type src_type,
+				  uint32_t log2_samples)
 {
 	VkResult result;
 	const char *name;
@@ -1009,7 +1084,7 @@  blit2d_init_stencil_only_pipeline(struct radv_device *device,
 	const VkPipelineVertexInputStateCreateInfo *vi_create_info;
 	struct radv_shader_module fs = { .nir = NULL };
 
-	fs.nir = build_nir_copy_fragment_shader_stencil(device, src_func, name, src_type == BLIT2D_SRC_TYPE_IMAGE_3D);
+	fs.nir = build_nir_copy_fragment_shader_stencil(device, src_func, name, src_type == BLIT2D_SRC_TYPE_IMAGE_3D, log2_samples > 0);
 	vi_create_info = &normal_vi_create_info;
 
 	struct radv_shader_module vs = {
@@ -1033,7 +1108,7 @@  blit2d_init_stencil_only_pipeline(struct radv_device *device,
 	};
 
 	for (enum radv_blit_ds_layout ds_layout = RADV_BLIT_DS_LAYOUT_TILE_ENABLE; ds_layout < RADV_BLIT_DS_LAYOUT_COUNT; ds_layout++) {
-		if (!device->meta_state.blit2d.stencil_only_rp[ds_layout]) {
+		if (!device->meta_state.blit2d_stencil_only_rp[ds_layout]) {
 			VkImageLayout layout = radv_meta_blit_ds_to_layout(ds_layout);
 			result = radv_CreateRenderPass(radv_device_to_handle(device),
 						       &(VkRenderPassCreateInfo) {
@@ -1061,7 +1136,7 @@  blit2d_init_stencil_only_pipeline(struct radv_device *device,
 								       .pPreserveAttachments = (uint32_t[]) { 0 },
 							       },
 							       .dependencyCount = 0,
-						       }, &device->meta_state.alloc, &device->meta_state.blit2d.stencil_only_rp[ds_layout]);
+						       }, &device->meta_state.alloc, &device->meta_state.blit2d_stencil_only_rp[ds_layout]);
 		}
 	}
 
@@ -1089,7 +1164,7 @@  blit2d_init_stencil_only_pipeline(struct radv_device *device,
 		},
 		.pMultisampleState = &(VkPipelineMultisampleStateCreateInfo) {
 			.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
-			.rasterizationSamples = 1,
+			.rasterizationSamples = 1 << log2_samples,
 			.sampleShadingEnable = false,
 			.pSampleMask = (VkSampleMask[]) { UINT32_MAX },
 		},
@@ -1136,8 +1211,8 @@  blit2d_init_stencil_only_pipeline(struct radv_device *device,
 			},
 		},
 		.flags = 0,
-		.layout = device->meta_state.blit2d.p_layouts[src_type],
-		.renderPass = device->meta_state.blit2d.stencil_only_rp[0],
+		.layout = device->meta_state.blit2d[log2_samples].p_layouts[src_type],
+		.renderPass = device->meta_state.blit2d_stencil_only_rp[0],
 		.subpass = 0,
 	};
 
@@ -1149,7 +1224,7 @@  blit2d_init_stencil_only_pipeline(struct radv_device *device,
 					       radv_pipeline_cache_to_handle(&device->meta_state.cache),
 					       &vk_pipeline_info, &radv_pipeline_info,
 					       &device->meta_state.alloc,
-					       &device->meta_state.blit2d.stencil_only_pipeline[src_type]);
+					       &device->meta_state.blit2d[log2_samples].stencil_only_pipeline[src_type]);
 
 
 	ralloc_free(vs.nir);
@@ -1175,15 +1250,16 @@  static VkFormat pipeline_formats[] = {
 
 static VkResult
 meta_blit2d_create_pipe_layout(struct radv_device *device,
-			       int idx)
+			       int idx,
+			       uint32_t log2_samples)
 {
 	VkResult result;
 	VkDescriptorType desc_type = (idx == BLIT2D_SRC_TYPE_BUFFER) ? VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER : VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
 	const VkPushConstantRange push_constant_ranges[] = {
 		{VK_SHADER_STAGE_VERTEX_BIT, 0, 16},
-		{VK_SHADER_STAGE_FRAGMENT_BIT, 16, 4},
+		{VK_SHADER_STAGE_FRAGMENT_BIT, 16, 12},
 	};
-	int num_push_constant_range = (idx != BLIT2D_SRC_TYPE_IMAGE) ? 2 : 1;
+	int num_push_constant_range = (idx != BLIT2D_SRC_TYPE_IMAGE || log2_samples > 0) ? 2 : 1;
 
 	result = radv_CreateDescriptorSetLayout(radv_device_to_handle(device),
 						&(VkDescriptorSetLayoutCreateInfo) {
@@ -1199,7 +1275,7 @@  meta_blit2d_create_pipe_layout(struct radv_device *device,
 								.pImmutableSamplers = NULL
 							},
 							}
-						}, &device->meta_state.alloc, &device->meta_state.blit2d.ds_layouts[idx]);
+						}, &device->meta_state.alloc, &device->meta_state.blit2d[log2_samples].ds_layouts[idx]);
 	if (result != VK_SUCCESS)
 		goto fail;
 
@@ -1207,11 +1283,11 @@  meta_blit2d_create_pipe_layout(struct radv_device *device,
 					   &(VkPipelineLayoutCreateInfo) {
 						   .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
 							   .setLayoutCount = 1,
-							   .pSetLayouts = &device->meta_state.blit2d.ds_layouts[idx],
+							   .pSetLayouts = &device->meta_state.blit2d[log2_samples].ds_layouts[idx],
 							   .pushConstantRangeCount = num_push_constant_range,
 							   .pPushConstantRanges = push_constant_ranges,
 							   },
-					   &device->meta_state.alloc, &device->meta_state.blit2d.p_layouts[idx]);
+					   &device->meta_state.alloc, &device->meta_state.blit2d[log2_samples].p_layouts[idx]);
 	if (result != VK_SUCCESS)
 		goto fail;
 	return VK_SUCCESS;
@@ -1225,27 +1301,33 @@  radv_device_init_meta_blit2d_state(struct radv_device *device)
 	VkResult result;
 	bool create_3d = device->physical_device->rad_info.chip_class >= GFX9;
 
-	for (unsigned src = 0; src < BLIT2D_NUM_SRC_TYPES; src++) {
-		if (src == BLIT2D_SRC_TYPE_IMAGE_3D && !create_3d)
-			continue;
+	for (unsigned log2_samples = 0; log2_samples < 1 + MAX_SAMPLES_LOG2; log2_samples++) {
+		for (unsigned src = 0; src < BLIT2D_NUM_SRC_TYPES; src++) {
+			if (src == BLIT2D_SRC_TYPE_IMAGE_3D && !create_3d)
+				continue;
 
-		result = meta_blit2d_create_pipe_layout(device, src);
-		if (result != VK_SUCCESS)
-			goto fail;
+			/* Don't need to handle copies between buffers and multisample images. */
+			if (src == BLIT2D_SRC_TYPE_BUFFER && log2_samples > 0)
+				continue;
 
-		for (unsigned j = 0; j < ARRAY_SIZE(pipeline_formats); ++j) {
-			result = blit2d_init_color_pipeline(device, src, pipeline_formats[j]);
+			result = meta_blit2d_create_pipe_layout(device, src, log2_samples);
 			if (result != VK_SUCCESS)
 				goto fail;
-		}
 
-		result = blit2d_init_depth_only_pipeline(device, src);
-		if (result != VK_SUCCESS)
-			goto fail;
+			for (unsigned j = 0; j < ARRAY_SIZE(pipeline_formats); ++j) {
+				result = blit2d_init_color_pipeline(device, src, pipeline_formats[j], log2_samples);
+				if (result != VK_SUCCESS)
+					goto fail;
+			}
+
+			result = blit2d_init_depth_only_pipeline(device, src, log2_samples);
+			if (result != VK_SUCCESS)
+				goto fail;
 
-		result = blit2d_init_stencil_only_pipeline(device, src);
-		if (result != VK_SUCCESS)
-			goto fail;
+			result = blit2d_init_stencil_only_pipeline(device, src, log2_samples);
+			if (result != VK_SUCCESS)
+				goto fail;
+		}
 	}
 
 	return VK_SUCCESS;
diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h
index 883342ede88..5d67271961b 100644
--- a/src/amd/vulkan/radv_private.h
+++ b/src/amd/vulkan/radv_private.h
@@ -465,18 +465,18 @@  struct radv_meta_state {
 	} blit;
 
 	struct {
-		VkRenderPass render_passes[NUM_META_FS_KEYS][RADV_META_DST_LAYOUT_COUNT];
+		VkPipelineLayout p_layouts[5];
+		VkDescriptorSetLayout ds_layouts[5];
+		VkPipeline pipelines[5][NUM_META_FS_KEYS];
 
-		VkPipelineLayout p_layouts[3];
-		VkDescriptorSetLayout ds_layouts[3];
-		VkPipeline pipelines[3][NUM_META_FS_KEYS];
+		VkPipeline depth_only_pipeline[5];
 
-		VkRenderPass depth_only_rp[RADV_BLIT_DS_LAYOUT_COUNT];
-		VkPipeline depth_only_pipeline[3];
+		VkPipeline stencil_only_pipeline[5];
+	} blit2d[1 + MAX_SAMPLES_LOG2];
 
-		VkRenderPass stencil_only_rp[RADV_BLIT_DS_LAYOUT_COUNT];
-		VkPipeline stencil_only_pipeline[3];
-	} blit2d;
+	VkRenderPass blit2d_render_passes[NUM_META_FS_KEYS][RADV_META_DST_LAYOUT_COUNT];
+	VkRenderPass blit2d_depth_only_rp[RADV_BLIT_DS_LAYOUT_COUNT];
+	VkRenderPass blit2d_stencil_only_rp[RADV_BLIT_DS_LAYOUT_COUNT];
 
 	struct {
 		VkPipelineLayout                          img_p_layout;

Comments

Matthew, can you double-check if v2 still fixes the issue for you? Thanks!

On 04/27/2018 01:23 PM, Samuel Pitoiset wrote:
> From: Matthew Nicholls <mnicholls@feralinteractive.com>
> 
> Previously before fb077b0728, the LOD parameter was being used in place of the
> sample index, which would only copy the first sample to all samples in the
> destination image. After that multisample image copies wouldn't copy anything
> from my observations.
> 
> This fixes some copy_and_blit CTS tests.
> 
> v2: - use GLSL_SAMPLER_DIM_MS instead of 2D (Samuel)
>      - updated commit description (Samuel)
> 
> Fix this properly by copying each sample in a separate radv_CmdDraw and using a
> pipeline with the correct rasterizationSamples for the destination image.
> 
> Cc: 18.0 18.1 <mesa-stable@lists.freedesktop.org>
> ---
>   src/amd/vulkan/radv_meta_blit2d.c | 282 +++++++++++++++++++-----------
>   src/amd/vulkan/radv_private.h     |  18 +-
>   2 files changed, 191 insertions(+), 109 deletions(-)
> 
> diff --git a/src/amd/vulkan/radv_meta_blit2d.c b/src/amd/vulkan/radv_meta_blit2d.c
> index e163056257e..3ad032f5989 100644
> --- a/src/amd/vulkan/radv_meta_blit2d.c
> +++ b/src/amd/vulkan/radv_meta_blit2d.c
> @@ -100,7 +100,8 @@ blit2d_bind_src(struct radv_cmd_buffer *cmd_buffer,
>                   struct radv_meta_blit2d_buffer *src_buf,
>                   struct blit2d_src_temps *tmp,
>                   enum blit2d_src_type src_type, VkFormat depth_format,
> -                VkImageAspectFlagBits aspects)
> +                VkImageAspectFlagBits aspects,
> +                uint32_t log2_samples)
>   {
>   	struct radv_device *device = cmd_buffer->device;
>   
> @@ -108,7 +109,7 @@ blit2d_bind_src(struct radv_cmd_buffer *cmd_buffer,
>   		create_bview(cmd_buffer, src_buf, &tmp->bview, depth_format);
>   
>   		radv_meta_push_descriptor_set(cmd_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
> -					      device->meta_state.blit2d.p_layouts[src_type],
> +					      device->meta_state.blit2d[log2_samples].p_layouts[src_type],
>   					      0, /* set */
>   					      1, /* descriptorWriteCount */
>   					      (VkWriteDescriptorSet[]) {
> @@ -123,7 +124,7 @@ blit2d_bind_src(struct radv_cmd_buffer *cmd_buffer,
>   					      });
>   
>   		radv_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer),
> -				      device->meta_state.blit2d.p_layouts[src_type],
> +				      device->meta_state.blit2d[log2_samples].p_layouts[src_type],
>   				      VK_SHADER_STAGE_FRAGMENT_BIT, 16, 4,
>   				      &src_buf->pitch);
>   	} else {
> @@ -131,12 +132,12 @@ blit2d_bind_src(struct radv_cmd_buffer *cmd_buffer,
>   
>   		if (src_type == BLIT2D_SRC_TYPE_IMAGE_3D)
>   			radv_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer),
> -					      device->meta_state.blit2d.p_layouts[src_type],
> +					      device->meta_state.blit2d[log2_samples].p_layouts[src_type],
>   					      VK_SHADER_STAGE_FRAGMENT_BIT, 16, 4,
>   					      &src_img->layer);
>   
>   		radv_meta_push_descriptor_set(cmd_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
> -					      device->meta_state.blit2d.p_layouts[src_type],
> +					      device->meta_state.blit2d[log2_samples].p_layouts[src_type],
>   					      0, /* set */
>   					      1, /* descriptorWriteCount */
>   					      (VkWriteDescriptorSet[]) {
> @@ -190,10 +191,11 @@ blit2d_bind_dst(struct radv_cmd_buffer *cmd_buffer,
>   
>   static void
>   bind_pipeline(struct radv_cmd_buffer *cmd_buffer,
> -              enum blit2d_src_type src_type, unsigned fs_key)
> +              enum blit2d_src_type src_type, unsigned fs_key,
> +              uint32_t log2_samples)
>   {
>   	VkPipeline pipeline =
> -		cmd_buffer->device->meta_state.blit2d.pipelines[src_type][fs_key];
> +		cmd_buffer->device->meta_state.blit2d[log2_samples].pipelines[src_type][fs_key];
>   
>   	radv_CmdBindPipeline(radv_cmd_buffer_to_handle(cmd_buffer),
>   			     VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
> @@ -201,10 +203,11 @@ bind_pipeline(struct radv_cmd_buffer *cmd_buffer,
>   
>   static void
>   bind_depth_pipeline(struct radv_cmd_buffer *cmd_buffer,
> -		    enum blit2d_src_type src_type)
> +		    enum blit2d_src_type src_type,
> +		    uint32_t log2_samples)
>   {
>   	VkPipeline pipeline =
> -		cmd_buffer->device->meta_state.blit2d.depth_only_pipeline[src_type];
> +		cmd_buffer->device->meta_state.blit2d[log2_samples].depth_only_pipeline[src_type];
>   
>   	radv_CmdBindPipeline(radv_cmd_buffer_to_handle(cmd_buffer),
>   			     VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
> @@ -212,10 +215,11 @@ bind_depth_pipeline(struct radv_cmd_buffer *cmd_buffer,
>   
>   static void
>   bind_stencil_pipeline(struct radv_cmd_buffer *cmd_buffer,
> -		      enum blit2d_src_type src_type)
> +		      enum blit2d_src_type src_type,
> +		      uint32_t log2_samples)
>   {
>   	VkPipeline pipeline =
> -		cmd_buffer->device->meta_state.blit2d.stencil_only_pipeline[src_type];
> +		cmd_buffer->device->meta_state.blit2d[log2_samples].stencil_only_pipeline[src_type];
>   
>   	radv_CmdBindPipeline(radv_cmd_buffer_to_handle(cmd_buffer),
>   			     VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
> @@ -227,7 +231,8 @@ radv_meta_blit2d_normal_dst(struct radv_cmd_buffer *cmd_buffer,
>   			    struct radv_meta_blit2d_buffer *src_buf,
>   			    struct radv_meta_blit2d_surf *dst,
>   			    unsigned num_rects,
> -			    struct radv_meta_blit2d_rect *rects, enum blit2d_src_type src_type)
> +			    struct radv_meta_blit2d_rect *rects, enum blit2d_src_type src_type,
> +			    uint32_t log2_samples)
>   {
>   	struct radv_device *device = cmd_buffer->device;
>   
> @@ -241,7 +246,7 @@ radv_meta_blit2d_normal_dst(struct radv_cmd_buffer *cmd_buffer,
>   			else if (aspect_mask == VK_IMAGE_ASPECT_DEPTH_BIT)
>   				depth_format = vk_format_depth_only(dst->image->vk_format);
>   			struct blit2d_src_temps src_temps;
> -			blit2d_bind_src(cmd_buffer, src_img, src_buf, &src_temps, src_type, depth_format, aspect_mask);
> +			blit2d_bind_src(cmd_buffer, src_img, src_buf, &src_temps, src_type, depth_format, aspect_mask, log2_samples);
>   
>   			struct blit2d_dst_temps dst_temps;
>   			blit2d_bind_dst(cmd_buffer, dst, rects[r].dst_x + rects[r].width,
> @@ -255,7 +260,7 @@ radv_meta_blit2d_normal_dst(struct radv_cmd_buffer *cmd_buffer,
>   			};
>   
>   			radv_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer),
> -					device->meta_state.blit2d.p_layouts[src_type],
> +					device->meta_state.blit2d[log2_samples].p_layouts[src_type],
>   					VK_SHADER_STAGE_VERTEX_BIT, 0, 16,
>   					vertex_push_constants);
>   
> @@ -266,7 +271,7 @@ radv_meta_blit2d_normal_dst(struct radv_cmd_buffer *cmd_buffer,
>   				radv_CmdBeginRenderPass(radv_cmd_buffer_to_handle(cmd_buffer),
>   							&(VkRenderPassBeginInfo) {
>   								.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
> -									.renderPass = device->meta_state.blit2d.render_passes[fs_key][dst_layout],
> +									.renderPass = device->meta_state.blit2d_render_passes[fs_key][dst_layout],
>   									.framebuffer = dst_temps.fb,
>   									.renderArea = {
>   									.offset = { rects[r].dst_x, rects[r].dst_y, },
> @@ -277,13 +282,13 @@ radv_meta_blit2d_normal_dst(struct radv_cmd_buffer *cmd_buffer,
>   										}, VK_SUBPASS_CONTENTS_INLINE);
>   
>   
> -				bind_pipeline(cmd_buffer, src_type, fs_key);
> +				bind_pipeline(cmd_buffer, src_type, fs_key, log2_samples);
>   			} else if (aspect_mask == VK_IMAGE_ASPECT_DEPTH_BIT) {
>   				enum radv_blit_ds_layout ds_layout = radv_meta_blit_ds_to_type(dst->current_layout);
>   				radv_CmdBeginRenderPass(radv_cmd_buffer_to_handle(cmd_buffer),
>   							&(VkRenderPassBeginInfo) {
>   								.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
> -									.renderPass = device->meta_state.blit2d.depth_only_rp[ds_layout],
> +									.renderPass = device->meta_state.blit2d_depth_only_rp[ds_layout],
>   									.framebuffer = dst_temps.fb,
>   									.renderArea = {
>   									.offset = { rects[r].dst_x, rects[r].dst_y, },
> @@ -294,14 +299,14 @@ radv_meta_blit2d_normal_dst(struct radv_cmd_buffer *cmd_buffer,
>   										}, VK_SUBPASS_CONTENTS_INLINE);
>   
>   
> -				bind_depth_pipeline(cmd_buffer, src_type);
> +				bind_depth_pipeline(cmd_buffer, src_type, log2_samples);
>   
>   			} else if (aspect_mask == VK_IMAGE_ASPECT_STENCIL_BIT) {
>   				enum radv_blit_ds_layout ds_layout = radv_meta_blit_ds_to_type(dst->current_layout);
>   				radv_CmdBeginRenderPass(radv_cmd_buffer_to_handle(cmd_buffer),
>   							&(VkRenderPassBeginInfo) {
>   								.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
> -									.renderPass = device->meta_state.blit2d.stencil_only_rp[ds_layout],
> +									.renderPass = device->meta_state.blit2d_stencil_only_rp[ds_layout],
>   									.framebuffer = dst_temps.fb,
>   									.renderArea = {
>   									.offset = { rects[r].dst_x, rects[r].dst_y, },
> @@ -312,7 +317,7 @@ radv_meta_blit2d_normal_dst(struct radv_cmd_buffer *cmd_buffer,
>   										}, VK_SUBPASS_CONTENTS_INLINE);
>   
>   
> -				bind_stencil_pipeline(cmd_buffer, src_type);
> +				bind_stencil_pipeline(cmd_buffer, src_type, log2_samples);
>   			} else
>   				unreachable("Processing blit2d with multiple aspects.");
>   
> @@ -332,7 +337,24 @@ radv_meta_blit2d_normal_dst(struct radv_cmd_buffer *cmd_buffer,
>   
>   
>   
> -			radv_CmdDraw(radv_cmd_buffer_to_handle(cmd_buffer), 3, 1, 0, 0);
> +			if (log2_samples > 0) {
> +				for (uint32_t sample = 0; sample < src_img->image->info.samples; sample++) {
> +					uint32_t sample_mask = 1 << sample;
> +					radv_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer),
> +							      device->meta_state.blit2d[log2_samples].p_layouts[src_type],
> +							      VK_SHADER_STAGE_FRAGMENT_BIT, 20, 4,
> +							      &sample);
> +
> +					radv_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer),
> +							      device->meta_state.blit2d[log2_samples].p_layouts[src_type],
> +							      VK_SHADER_STAGE_FRAGMENT_BIT, 24, 4,
> +							      &sample_mask);
> +
> +					radv_CmdDraw(radv_cmd_buffer_to_handle(cmd_buffer), 3, 1, 0, 0);
> +				}
> +			}
> +			else
> +				radv_CmdDraw(radv_cmd_buffer_to_handle(cmd_buffer), 3, 1, 0, 0);
>   			radv_CmdEndRenderPass(radv_cmd_buffer_to_handle(cmd_buffer));
>   
>   			/* At the point where we emit the draw call, all data from the
> @@ -358,7 +380,8 @@ radv_meta_blit2d(struct radv_cmd_buffer *cmd_buffer,
>   	enum blit2d_src_type src_type = src_buf ? BLIT2D_SRC_TYPE_BUFFER :
>   		use_3d ? BLIT2D_SRC_TYPE_IMAGE_3D : BLIT2D_SRC_TYPE_IMAGE;
>   	radv_meta_blit2d_normal_dst(cmd_buffer, src_img, src_buf, dst,
> -				    num_rects, rects, src_type);
> +				    num_rects, rects, src_type,
> +				    src_img ? util_logbase2(src_img->image->info.samples) : 0);
>   }
>   
>   static nir_shader *
> @@ -421,13 +444,14 @@ build_nir_vertex_shader(void)
>   
>   typedef nir_ssa_def* (*texel_fetch_build_func)(struct nir_builder *,
>                                                  struct radv_device *,
> -                                               nir_ssa_def *, bool);
> +                                               nir_ssa_def *, bool, bool);
>   
>   static nir_ssa_def *
>   build_nir_texel_fetch(struct nir_builder *b, struct radv_device *device,
> -                      nir_ssa_def *tex_pos, bool is_3d)
> +                      nir_ssa_def *tex_pos, bool is_3d, bool is_multisampled)
>   {
> -	enum glsl_sampler_dim dim = is_3d ? GLSL_SAMPLER_DIM_3D : GLSL_SAMPLER_DIM_2D;
> +	enum glsl_sampler_dim dim =
> +		is_3d ? GLSL_SAMPLER_DIM_3D : is_multisampled ? GLSL_SAMPLER_DIM_MS : GLSL_SAMPLER_DIM_2D;
>   	const struct glsl_type *sampler_type =
>   		glsl_sampler_type(dim, false, false, GLSL_TYPE_UINT);
>   	nir_variable *sampler = nir_variable_create(b->shader, nir_var_uniform,
> @@ -436,6 +460,7 @@ build_nir_texel_fetch(struct nir_builder *b, struct radv_device *device,
>   	sampler->data.binding = 0;
>   
>   	nir_ssa_def *tex_pos_3d = NULL;
> +	nir_intrinsic_instr *sample_idx = NULL;
>   	if (is_3d) {
>   		nir_intrinsic_instr *layer = nir_intrinsic_instr_create(b->shader, nir_intrinsic_load_push_constant);
>   		nir_intrinsic_set_base(layer, 16);
> @@ -451,13 +476,22 @@ build_nir_texel_fetch(struct nir_builder *b, struct radv_device *device,
>   		chans[2] = &layer->dest.ssa;
>   		tex_pos_3d = nir_vec(b, chans, 3);
>   	}
> +	if (is_multisampled) {
> +		sample_idx = nir_intrinsic_instr_create(b->shader, nir_intrinsic_load_push_constant);
> +		nir_intrinsic_set_base(sample_idx, 20);
> +		nir_intrinsic_set_range(sample_idx, 4);
> +		sample_idx->src[0] = nir_src_for_ssa(nir_imm_int(b, 0));
> +		sample_idx->num_components = 1;
> +		nir_ssa_dest_init(&sample_idx->instr, &sample_idx->dest, 1, 32, "sample_idx");
> +		nir_builder_instr_insert(b, &sample_idx->instr);
> +	}
>   	nir_tex_instr *tex = nir_tex_instr_create(b->shader, 2);
>   	tex->sampler_dim = dim;
> -	tex->op = nir_texop_txf;
> +	tex->op = is_multisampled ? nir_texop_txf_ms : nir_texop_txf;
>   	tex->src[0].src_type = nir_tex_src_coord;
>   	tex->src[0].src = nir_src_for_ssa(is_3d ? tex_pos_3d : tex_pos);
> -	tex->src[1].src_type = nir_tex_src_lod;
> -	tex->src[1].src = nir_src_for_ssa(nir_imm_int(b, 0));
> +	tex->src[1].src_type = is_multisampled ? nir_tex_src_ms_index : nir_tex_src_lod;
> +	tex->src[1].src = nir_src_for_ssa(is_multisampled ? &sample_idx->dest.ssa : nir_imm_int(b, 0));
>   	tex->dest_type = nir_type_uint;
>   	tex->is_array = false;
>   	tex->coord_components = is_3d ? 3 : 2;
> @@ -473,7 +507,7 @@ build_nir_texel_fetch(struct nir_builder *b, struct radv_device *device,
>   
>   static nir_ssa_def *
>   build_nir_buffer_fetch(struct nir_builder *b, struct radv_device *device,
> -		       nir_ssa_def *tex_pos, bool is_3d)
> +		       nir_ssa_def *tex_pos, bool is_3d, bool is_multisampled)
>   {
>   	const struct glsl_type *sampler_type =
>   		glsl_sampler_type(GLSL_SAMPLER_DIM_BUF, false, false, GLSL_TYPE_UINT);
> @@ -519,9 +553,31 @@ static const VkPipelineVertexInputStateCreateInfo normal_vi_create_info = {
>   	.vertexAttributeDescriptionCount = 0,
>   };
>   
> +static void
> +build_nir_store_sample_mask(struct nir_builder *b)
> +{
> +	nir_intrinsic_instr *sample_mask = nir_intrinsic_instr_create(b->shader, nir_intrinsic_load_push_constant);
> +	nir_intrinsic_set_base(sample_mask, 24);
> +	nir_intrinsic_set_range(sample_mask, 4);
> +	sample_mask->src[0] = nir_src_for_ssa(nir_imm_int(b, 0));
> +	sample_mask->num_components = 1;
> +	nir_ssa_dest_init(&sample_mask->instr, &sample_mask->dest, 1, 32, "sample_mask");
> +	nir_builder_instr_insert(b, &sample_mask->instr);
> +
> +	const struct glsl_type *sample_mask_out_type = glsl_uint_type();
> +
> +	nir_variable *sample_mask_out =
> +		nir_variable_create(b->shader, nir_var_shader_out,
> +				    sample_mask_out_type, "sample_mask_out");
> +	sample_mask_out->data.location = FRAG_RESULT_SAMPLE_MASK;
> +
> +	nir_store_var(b, sample_mask_out, &sample_mask->dest.ssa, 0x1);
> +}
> +
>   static nir_shader *
>   build_nir_copy_fragment_shader(struct radv_device *device,
> -                               texel_fetch_build_func txf_func, const char* name, bool is_3d)
> +                               texel_fetch_build_func txf_func, const char* name, bool is_3d,
> +                               bool is_multisampled)
>   {
>   	const struct glsl_type *vec4 = glsl_vec4_type();
>   	const struct glsl_type *vec2 = glsl_vector_type(GLSL_TYPE_FLOAT, 2);
> @@ -538,11 +594,15 @@ build_nir_copy_fragment_shader(struct radv_device *device,
>   						      vec4, "f_color");
>   	color_out->data.location = FRAG_RESULT_DATA0;
>   
> +	if (is_multisampled) {
> +		build_nir_store_sample_mask(&b);
> +	}
> +
>   	nir_ssa_def *pos_int = nir_f2i32(&b, nir_load_var(&b, tex_pos_in));
>   	unsigned swiz[4] = { 0, 1 };
>   	nir_ssa_def *tex_pos = nir_swizzle(&b, pos_int, swiz, 2, false);
>   
> -	nir_ssa_def *color = txf_func(&b, device, tex_pos, is_3d);
> +	nir_ssa_def *color = txf_func(&b, device, tex_pos, is_3d, is_multisampled);
>   	nir_store_var(&b, color_out, color, 0xf);
>   
>   	return b.shader;
> @@ -550,7 +610,8 @@ build_nir_copy_fragment_shader(struct radv_device *device,
>   
>   static nir_shader *
>   build_nir_copy_fragment_shader_depth(struct radv_device *device,
> -				     texel_fetch_build_func txf_func, const char* name, bool is_3d)
> +				     texel_fetch_build_func txf_func, const char* name, bool is_3d,
> +				     bool is_multisampled)
>   {
>   	const struct glsl_type *vec4 = glsl_vec4_type();
>   	const struct glsl_type *vec2 = glsl_vector_type(GLSL_TYPE_FLOAT, 2);
> @@ -567,11 +628,15 @@ build_nir_copy_fragment_shader_depth(struct radv_device *device,
>   						      vec4, "f_color");
>   	color_out->data.location = FRAG_RESULT_DEPTH;
>   
> +	if (is_multisampled) {
> +		build_nir_store_sample_mask(&b);
> +	}
> +
>   	nir_ssa_def *pos_int = nir_f2i32(&b, nir_load_var(&b, tex_pos_in));
>   	unsigned swiz[4] = { 0, 1 };
>   	nir_ssa_def *tex_pos = nir_swizzle(&b, pos_int, swiz, 2, false);
>   
> -	nir_ssa_def *color = txf_func(&b, device, tex_pos, is_3d);
> +	nir_ssa_def *color = txf_func(&b, device, tex_pos, is_3d, is_multisampled);
>   	nir_store_var(&b, color_out, color, 0x1);
>   
>   	return b.shader;
> @@ -579,7 +644,8 @@ build_nir_copy_fragment_shader_depth(struct radv_device *device,
>   
>   static nir_shader *
>   build_nir_copy_fragment_shader_stencil(struct radv_device *device,
> -				       texel_fetch_build_func txf_func, const char* name, bool is_3d)
> +				       texel_fetch_build_func txf_func, const char* name, bool is_3d,
> +				       bool is_multisampled)
>   {
>   	const struct glsl_type *vec4 = glsl_vec4_type();
>   	const struct glsl_type *vec2 = glsl_vector_type(GLSL_TYPE_FLOAT, 2);
> @@ -596,11 +662,15 @@ build_nir_copy_fragment_shader_stencil(struct radv_device *device,
>   						      vec4, "f_color");
>   	color_out->data.location = FRAG_RESULT_STENCIL;
>   
> +	if (is_multisampled) {
> +		build_nir_store_sample_mask(&b);
> +	}
> +
>   	nir_ssa_def *pos_int = nir_f2i32(&b, nir_load_var(&b, tex_pos_in));
>   	unsigned swiz[4] = { 0, 1 };
>   	nir_ssa_def *tex_pos = nir_swizzle(&b, pos_int, swiz, 2, false);
>   
> -	nir_ssa_def *color = txf_func(&b, device, tex_pos, is_3d);
> +	nir_ssa_def *color = txf_func(&b, device, tex_pos, is_3d, is_multisampled);
>   	nir_store_var(&b, color_out, color, 0x1);
>   
>   	return b.shader;
> @@ -614,45 +684,48 @@ radv_device_finish_meta_blit2d_state(struct radv_device *device)
>   	for(unsigned j = 0; j < NUM_META_FS_KEYS; ++j) {
>   		for (unsigned k = 0; k < RADV_META_DST_LAYOUT_COUNT; ++k) {
>   			radv_DestroyRenderPass(radv_device_to_handle(device),
> -			                       state->blit2d.render_passes[j][k],
> -			                       &state->alloc);
> +					       state->blit2d_render_passes[j][k],
> +					       &state->alloc);
>   		}
>   	}
>   
>   	for (enum radv_blit_ds_layout j = RADV_BLIT_DS_LAYOUT_TILE_ENABLE; j < RADV_BLIT_DS_LAYOUT_COUNT; j++) {
>   		radv_DestroyRenderPass(radv_device_to_handle(device),
> -				       state->blit2d.depth_only_rp[j], &state->alloc);
> +				       state->blit2d_depth_only_rp[j], &state->alloc);
>   		radv_DestroyRenderPass(radv_device_to_handle(device),
> -				       state->blit2d.stencil_only_rp[j], &state->alloc);
> +				       state->blit2d_stencil_only_rp[j], &state->alloc);
>   	}
>   
> -	for (unsigned src = 0; src < BLIT2D_NUM_SRC_TYPES; src++) {
> -		radv_DestroyPipelineLayout(radv_device_to_handle(device),
> -					   state->blit2d.p_layouts[src],
> -					   &state->alloc);
> -		radv_DestroyDescriptorSetLayout(radv_device_to_handle(device),
> -						state->blit2d.ds_layouts[src],
> -						&state->alloc);
> +	for (unsigned log2_samples = 0; log2_samples < 1 + MAX_SAMPLES_LOG2; ++log2_samples) {
> +		for (unsigned src = 0; src < BLIT2D_NUM_SRC_TYPES; src++) {
> +			radv_DestroyPipelineLayout(radv_device_to_handle(device),
> +						   state->blit2d[log2_samples].p_layouts[src],
> +						   &state->alloc);
> +			radv_DestroyDescriptorSetLayout(radv_device_to_handle(device),
> +							state->blit2d[log2_samples].ds_layouts[src],
> +							&state->alloc);
> +
> +			for (unsigned j = 0; j < NUM_META_FS_KEYS; ++j) {
> +				radv_DestroyPipeline(radv_device_to_handle(device),
> +						     state->blit2d[log2_samples].pipelines[src][j],
> +						     &state->alloc);
> +			}
>   
> -		for (unsigned j = 0; j < NUM_META_FS_KEYS; ++j) {
>   			radv_DestroyPipeline(radv_device_to_handle(device),
> -					     state->blit2d.pipelines[src][j],
> +					     state->blit2d[log2_samples].depth_only_pipeline[src],
> +					     &state->alloc);
> +			radv_DestroyPipeline(radv_device_to_handle(device),
> +					     state->blit2d[log2_samples].stencil_only_pipeline[src],
>   					     &state->alloc);
>   		}
> -
> -		radv_DestroyPipeline(radv_device_to_handle(device),
> -				     state->blit2d.depth_only_pipeline[src],
> -				     &state->alloc);
> -		radv_DestroyPipeline(radv_device_to_handle(device),
> -				     state->blit2d.stencil_only_pipeline[src],
> -				     &state->alloc);
>   	}
>   }
>   
>   static VkResult
>   blit2d_init_color_pipeline(struct radv_device *device,
>   			   enum blit2d_src_type src_type,
> -			   VkFormat format)
> +			   VkFormat format,
> +			   uint32_t log2_samples)
>   {
>   	VkResult result;
>   	unsigned fs_key = radv_format_meta_fs_key(format);
> @@ -681,7 +754,7 @@ blit2d_init_color_pipeline(struct radv_device *device,
>   	struct radv_shader_module fs = { .nir = NULL };
>   
>   
> -	fs.nir = build_nir_copy_fragment_shader(device, src_func, name, src_type == BLIT2D_SRC_TYPE_IMAGE_3D);
> +	fs.nir = build_nir_copy_fragment_shader(device, src_func, name, src_type == BLIT2D_SRC_TYPE_IMAGE_3D, log2_samples > 0);
>   	vi_create_info = &normal_vi_create_info;
>   
>   	struct radv_shader_module vs = {
> @@ -705,7 +778,7 @@ blit2d_init_color_pipeline(struct radv_device *device,
>   	};
>   
>   	for (unsigned dst_layout = 0; dst_layout < RADV_META_DST_LAYOUT_COUNT; ++dst_layout) {
> -		if (!device->meta_state.blit2d.render_passes[fs_key][dst_layout]) {
> +		if (!device->meta_state.blit2d_render_passes[fs_key][dst_layout]) {
>   			VkImageLayout layout = radv_meta_dst_layout_to_layout(dst_layout);
>   
>   			result = radv_CreateRenderPass(radv_device_to_handle(device),
> @@ -737,7 +810,7 @@ blit2d_init_color_pipeline(struct radv_device *device,
>   						.pPreserveAttachments = (uint32_t[]) { 0 },
>   						},
>   						.dependencyCount = 0,
> -					}, &device->meta_state.alloc, &device->meta_state.blit2d.render_passes[fs_key][dst_layout]);
> +					}, &device->meta_state.alloc, &device->meta_state.blit2d_render_passes[fs_key][dst_layout]);
>   		}
>   	}
>   
> @@ -765,7 +838,7 @@ blit2d_init_color_pipeline(struct radv_device *device,
>   		},
>   		.pMultisampleState = &(VkPipelineMultisampleStateCreateInfo) {
>   			.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
> -			.rasterizationSamples = 1,
> +			.rasterizationSamples = 1 << log2_samples,
>   			.sampleShadingEnable = false,
>   			.pSampleMask = (VkSampleMask[]) { UINT32_MAX },
>   		},
> @@ -796,8 +869,8 @@ blit2d_init_color_pipeline(struct radv_device *device,
>   			},
>   		},
>   		.flags = 0,
> -		.layout = device->meta_state.blit2d.p_layouts[src_type],
> -		.renderPass = device->meta_state.blit2d.render_passes[fs_key][0],
> +		.layout = device->meta_state.blit2d[log2_samples].p_layouts[src_type],
> +		.renderPass = device->meta_state.blit2d_render_passes[fs_key][0],
>   		.subpass = 0,
>   	};
>   
> @@ -809,7 +882,7 @@ blit2d_init_color_pipeline(struct radv_device *device,
>   					       radv_pipeline_cache_to_handle(&device->meta_state.cache),
>   					       &vk_pipeline_info, &radv_pipeline_info,
>   					       &device->meta_state.alloc,
> -					       &device->meta_state.blit2d.pipelines[src_type][fs_key]);
> +					       &device->meta_state.blit2d[log2_samples].pipelines[src_type][fs_key]);
>   
>   
>   	ralloc_free(vs.nir);
> @@ -820,7 +893,8 @@ blit2d_init_color_pipeline(struct radv_device *device,
>   
>   static VkResult
>   blit2d_init_depth_only_pipeline(struct radv_device *device,
> -				enum blit2d_src_type src_type)
> +				enum blit2d_src_type src_type,
> +				uint32_t log2_samples)
>   {
>   	VkResult result;
>   	const char *name;
> @@ -847,7 +921,7 @@ blit2d_init_depth_only_pipeline(struct radv_device *device,
>   	const VkPipelineVertexInputStateCreateInfo *vi_create_info;
>   	struct radv_shader_module fs = { .nir = NULL };
>   
> -	fs.nir = build_nir_copy_fragment_shader_depth(device, src_func, name, src_type == BLIT2D_SRC_TYPE_IMAGE_3D);
> +	fs.nir = build_nir_copy_fragment_shader_depth(device, src_func, name, src_type == BLIT2D_SRC_TYPE_IMAGE_3D, log2_samples > 0);
>   	vi_create_info = &normal_vi_create_info;
>   
>   	struct radv_shader_module vs = {
> @@ -871,7 +945,7 @@ blit2d_init_depth_only_pipeline(struct radv_device *device,
>   	};
>   
>   	for (enum radv_blit_ds_layout ds_layout = RADV_BLIT_DS_LAYOUT_TILE_ENABLE; ds_layout < RADV_BLIT_DS_LAYOUT_COUNT; ds_layout++) {
> -		if (!device->meta_state.blit2d.depth_only_rp[ds_layout]) {
> +		if (!device->meta_state.blit2d_depth_only_rp[ds_layout]) {
>   			VkImageLayout layout = radv_meta_blit_ds_to_layout(ds_layout);
>   			result = radv_CreateRenderPass(radv_device_to_handle(device),
>   						       &(VkRenderPassCreateInfo) {
> @@ -899,7 +973,7 @@ blit2d_init_depth_only_pipeline(struct radv_device *device,
>   								       .pPreserveAttachments = (uint32_t[]) { 0 },
>   							       },
>   							       .dependencyCount = 0,
> -							}, &device->meta_state.alloc, &device->meta_state.blit2d.depth_only_rp[ds_layout]);
> +							}, &device->meta_state.alloc, &device->meta_state.blit2d_depth_only_rp[ds_layout]);
>   		}
>   	}
>   
> @@ -927,7 +1001,7 @@ blit2d_init_depth_only_pipeline(struct radv_device *device,
>   		},
>   		.pMultisampleState = &(VkPipelineMultisampleStateCreateInfo) {
>   			.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
> -			.rasterizationSamples = 1,
> +			.rasterizationSamples = 1 << log2_samples,
>   			.sampleShadingEnable = false,
>   			.pSampleMask = (VkSampleMask[]) { UINT32_MAX },
>   		},
> @@ -958,8 +1032,8 @@ blit2d_init_depth_only_pipeline(struct radv_device *device,
>   			},
>   		},
>   		.flags = 0,
> -		.layout = device->meta_state.blit2d.p_layouts[src_type],
> -		.renderPass = device->meta_state.blit2d.depth_only_rp[0],
> +		.layout = device->meta_state.blit2d[log2_samples].p_layouts[src_type],
> +		.renderPass = device->meta_state.blit2d_depth_only_rp[0],
>   		.subpass = 0,
>   	};
>   
> @@ -971,7 +1045,7 @@ blit2d_init_depth_only_pipeline(struct radv_device *device,
>   					       radv_pipeline_cache_to_handle(&device->meta_state.cache),
>   					       &vk_pipeline_info, &radv_pipeline_info,
>   					       &device->meta_state.alloc,
> -					       &device->meta_state.blit2d.depth_only_pipeline[src_type]);
> +					       &device->meta_state.blit2d[log2_samples].depth_only_pipeline[src_type]);
>   
>   
>   	ralloc_free(vs.nir);
> @@ -982,7 +1056,8 @@ blit2d_init_depth_only_pipeline(struct radv_device *device,
>   
>   static VkResult
>   blit2d_init_stencil_only_pipeline(struct radv_device *device,
> -				  enum blit2d_src_type src_type)
> +				  enum blit2d_src_type src_type,
> +				  uint32_t log2_samples)
>   {
>   	VkResult result;
>   	const char *name;
> @@ -1009,7 +1084,7 @@ blit2d_init_stencil_only_pipeline(struct radv_device *device,
>   	const VkPipelineVertexInputStateCreateInfo *vi_create_info;
>   	struct radv_shader_module fs = { .nir = NULL };
>   
> -	fs.nir = build_nir_copy_fragment_shader_stencil(device, src_func, name, src_type == BLIT2D_SRC_TYPE_IMAGE_3D);
> +	fs.nir = build_nir_copy_fragment_shader_stencil(device, src_func, name, src_type == BLIT2D_SRC_TYPE_IMAGE_3D, log2_samples > 0);
>   	vi_create_info = &normal_vi_create_info;
>   
>   	struct radv_shader_module vs = {
> @@ -1033,7 +1108,7 @@ blit2d_init_stencil_only_pipeline(struct radv_device *device,
>   	};
>   
>   	for (enum radv_blit_ds_layout ds_layout = RADV_BLIT_DS_LAYOUT_TILE_ENABLE; ds_layout < RADV_BLIT_DS_LAYOUT_COUNT; ds_layout++) {
> -		if (!device->meta_state.blit2d.stencil_only_rp[ds_layout]) {
> +		if (!device->meta_state.blit2d_stencil_only_rp[ds_layout]) {
>   			VkImageLayout layout = radv_meta_blit_ds_to_layout(ds_layout);
>   			result = radv_CreateRenderPass(radv_device_to_handle(device),
>   						       &(VkRenderPassCreateInfo) {
> @@ -1061,7 +1136,7 @@ blit2d_init_stencil_only_pipeline(struct radv_device *device,
>   								       .pPreserveAttachments = (uint32_t[]) { 0 },
>   							       },
>   							       .dependencyCount = 0,
> -						       }, &device->meta_state.alloc, &device->meta_state.blit2d.stencil_only_rp[ds_layout]);
> +						       }, &device->meta_state.alloc, &device->meta_state.blit2d_stencil_only_rp[ds_layout]);
>   		}
>   	}
>   
> @@ -1089,7 +1164,7 @@ blit2d_init_stencil_only_pipeline(struct radv_device *device,
>   		},
>   		.pMultisampleState = &(VkPipelineMultisampleStateCreateInfo) {
>   			.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
> -			.rasterizationSamples = 1,
> +			.rasterizationSamples = 1 << log2_samples,
>   			.sampleShadingEnable = false,
>   			.pSampleMask = (VkSampleMask[]) { UINT32_MAX },
>   		},
> @@ -1136,8 +1211,8 @@ blit2d_init_stencil_only_pipeline(struct radv_device *device,
>   			},
>   		},
>   		.flags = 0,
> -		.layout = device->meta_state.blit2d.p_layouts[src_type],
> -		.renderPass = device->meta_state.blit2d.stencil_only_rp[0],
> +		.layout = device->meta_state.blit2d[log2_samples].p_layouts[src_type],
> +		.renderPass = device->meta_state.blit2d_stencil_only_rp[0],
>   		.subpass = 0,
>   	};
>   
> @@ -1149,7 +1224,7 @@ blit2d_init_stencil_only_pipeline(struct radv_device *device,
>   					       radv_pipeline_cache_to_handle(&device->meta_state.cache),
>   					       &vk_pipeline_info, &radv_pipeline_info,
>   					       &device->meta_state.alloc,
> -					       &device->meta_state.blit2d.stencil_only_pipeline[src_type]);
> +					       &device->meta_state.blit2d[log2_samples].stencil_only_pipeline[src_type]);
>   
>   
>   	ralloc_free(vs.nir);
> @@ -1175,15 +1250,16 @@ static VkFormat pipeline_formats[] = {
>   
>   static VkResult
>   meta_blit2d_create_pipe_layout(struct radv_device *device,
> -			       int idx)
> +			       int idx,
> +			       uint32_t log2_samples)
>   {
>   	VkResult result;
>   	VkDescriptorType desc_type = (idx == BLIT2D_SRC_TYPE_BUFFER) ? VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER : VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
>   	const VkPushConstantRange push_constant_ranges[] = {
>   		{VK_SHADER_STAGE_VERTEX_BIT, 0, 16},
> -		{VK_SHADER_STAGE_FRAGMENT_BIT, 16, 4},
> +		{VK_SHADER_STAGE_FRAGMENT_BIT, 16, 12},
>   	};
> -	int num_push_constant_range = (idx != BLIT2D_SRC_TYPE_IMAGE) ? 2 : 1;
> +	int num_push_constant_range = (idx != BLIT2D_SRC_TYPE_IMAGE || log2_samples > 0) ? 2 : 1;
>   
>   	result = radv_CreateDescriptorSetLayout(radv_device_to_handle(device),
>   						&(VkDescriptorSetLayoutCreateInfo) {
> @@ -1199,7 +1275,7 @@ meta_blit2d_create_pipe_layout(struct radv_device *device,
>   								.pImmutableSamplers = NULL
>   							},
>   							}
> -						}, &device->meta_state.alloc, &device->meta_state.blit2d.ds_layouts[idx]);
> +						}, &device->meta_state.alloc, &device->meta_state.blit2d[log2_samples].ds_layouts[idx]);
>   	if (result != VK_SUCCESS)
>   		goto fail;
>   
> @@ -1207,11 +1283,11 @@ meta_blit2d_create_pipe_layout(struct radv_device *device,
>   					   &(VkPipelineLayoutCreateInfo) {
>   						   .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
>   							   .setLayoutCount = 1,
> -							   .pSetLayouts = &device->meta_state.blit2d.ds_layouts[idx],
> +							   .pSetLayouts = &device->meta_state.blit2d[log2_samples].ds_layouts[idx],
>   							   .pushConstantRangeCount = num_push_constant_range,
>   							   .pPushConstantRanges = push_constant_ranges,
>   							   },
> -					   &device->meta_state.alloc, &device->meta_state.blit2d.p_layouts[idx]);
> +					   &device->meta_state.alloc, &device->meta_state.blit2d[log2_samples].p_layouts[idx]);
>   	if (result != VK_SUCCESS)
>   		goto fail;
>   	return VK_SUCCESS;
> @@ -1225,27 +1301,33 @@ radv_device_init_meta_blit2d_state(struct radv_device *device)
>   	VkResult result;
>   	bool create_3d = device->physical_device->rad_info.chip_class >= GFX9;
>   
> -	for (unsigned src = 0; src < BLIT2D_NUM_SRC_TYPES; src++) {
> -		if (src == BLIT2D_SRC_TYPE_IMAGE_3D && !create_3d)
> -			continue;
> +	for (unsigned log2_samples = 0; log2_samples < 1 + MAX_SAMPLES_LOG2; log2_samples++) {
> +		for (unsigned src = 0; src < BLIT2D_NUM_SRC_TYPES; src++) {
> +			if (src == BLIT2D_SRC_TYPE_IMAGE_3D && !create_3d)
> +				continue;
>   
> -		result = meta_blit2d_create_pipe_layout(device, src);
> -		if (result != VK_SUCCESS)
> -			goto fail;
> +			/* Don't need to handle copies between buffers and multisample images. */
> +			if (src == BLIT2D_SRC_TYPE_BUFFER && log2_samples > 0)
> +				continue;
>   
> -		for (unsigned j = 0; j < ARRAY_SIZE(pipeline_formats); ++j) {
> -			result = blit2d_init_color_pipeline(device, src, pipeline_formats[j]);
> +			result = meta_blit2d_create_pipe_layout(device, src, log2_samples);
>   			if (result != VK_SUCCESS)
>   				goto fail;
> -		}
>   
> -		result = blit2d_init_depth_only_pipeline(device, src);
> -		if (result != VK_SUCCESS)
> -			goto fail;
> +			for (unsigned j = 0; j < ARRAY_SIZE(pipeline_formats); ++j) {
> +				result = blit2d_init_color_pipeline(device, src, pipeline_formats[j], log2_samples);
> +				if (result != VK_SUCCESS)
> +					goto fail;
> +			}
> +
> +			result = blit2d_init_depth_only_pipeline(device, src, log2_samples);
> +			if (result != VK_SUCCESS)
> +				goto fail;
>   
> -		result = blit2d_init_stencil_only_pipeline(device, src);
> -		if (result != VK_SUCCESS)
> -			goto fail;
> +			result = blit2d_init_stencil_only_pipeline(device, src, log2_samples);
> +			if (result != VK_SUCCESS)
> +				goto fail;
> +		}
>   	}
>   
>   	return VK_SUCCESS;
> diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h
> index 883342ede88..5d67271961b 100644
> --- a/src/amd/vulkan/radv_private.h
> +++ b/src/amd/vulkan/radv_private.h
> @@ -465,18 +465,18 @@ struct radv_meta_state {
>   	} blit;
>   
>   	struct {
> -		VkRenderPass render_passes[NUM_META_FS_KEYS][RADV_META_DST_LAYOUT_COUNT];
> +		VkPipelineLayout p_layouts[5];
> +		VkDescriptorSetLayout ds_layouts[5];
> +		VkPipeline pipelines[5][NUM_META_FS_KEYS];
>   
> -		VkPipelineLayout p_layouts[3];
> -		VkDescriptorSetLayout ds_layouts[3];
> -		VkPipeline pipelines[3][NUM_META_FS_KEYS];
> +		VkPipeline depth_only_pipeline[5];
>   
> -		VkRenderPass depth_only_rp[RADV_BLIT_DS_LAYOUT_COUNT];
> -		VkPipeline depth_only_pipeline[3];
> +		VkPipeline stencil_only_pipeline[5];
> +	} blit2d[1 + MAX_SAMPLES_LOG2];
>   
> -		VkRenderPass stencil_only_rp[RADV_BLIT_DS_LAYOUT_COUNT];
> -		VkPipeline stencil_only_pipeline[3];
> -	} blit2d;
> +	VkRenderPass blit2d_render_passes[NUM_META_FS_KEYS][RADV_META_DST_LAYOUT_COUNT];
> +	VkRenderPass blit2d_depth_only_rp[RADV_BLIT_DS_LAYOUT_COUNT];
> +	VkRenderPass blit2d_stencil_only_rp[RADV_BLIT_DS_LAYOUT_COUNT];
>   
>   	struct {
>   		VkPipelineLayout                          img_p_layout;
>
I've verified the V2 of my patch does still fix the original issue I was 
seeing.

Thanks a bunch.

Matthew.


On 27/04/18 12:26, Samuel Pitoiset wrote:
> Matthew, can you double-check if v2 still fixes the issue for you? 
> Thanks!
>
> On 04/27/2018 01:23 PM, Samuel Pitoiset wrote:
>> From: Matthew Nicholls <mnicholls@feralinteractive.com>
>>
>> Previously before fb077b0728, the LOD parameter was being used in 
>> place of the
>> sample index, which would only copy the first sample to all samples 
>> in the
>> destination image. After that multisample image copies wouldn't copy 
>> anything
>> from my observations.
>>
>> This fixes some copy_and_blit CTS tests.
>>
>> v2: - use GLSL_SAMPLER_DIM_MS instead of 2D (Samuel)
>>      - updated commit description (Samuel)
>>
>> Fix this properly by copying each sample in a separate radv_CmdDraw 
>> and using a
>> pipeline with the correct rasterizationSamples for the destination 
>> image.
>>
>> Cc: 18.0 18.1 <mesa-stable@lists.freedesktop.org>
>> ---
>>   src/amd/vulkan/radv_meta_blit2d.c | 282 +++++++++++++++++++-----------
>>   src/amd/vulkan/radv_private.h     |  18 +-
>>   2 files changed, 191 insertions(+), 109 deletions(-)
>>
>> diff --git a/src/amd/vulkan/radv_meta_blit2d.c 
>> b/src/amd/vulkan/radv_meta_blit2d.c
>> index e163056257e..3ad032f5989 100644
>> --- a/src/amd/vulkan/radv_meta_blit2d.c
>> +++ b/src/amd/vulkan/radv_meta_blit2d.c
>> @@ -100,7 +100,8 @@ blit2d_bind_src(struct radv_cmd_buffer *cmd_buffer,
>>                   struct radv_meta_blit2d_buffer *src_buf,
>>                   struct blit2d_src_temps *tmp,
>>                   enum blit2d_src_type src_type, VkFormat depth_format,
>> -                VkImageAspectFlagBits aspects)
>> +                VkImageAspectFlagBits aspects,
>> +                uint32_t log2_samples)
>>   {
>>       struct radv_device *device = cmd_buffer->device;
>>   @@ -108,7 +109,7 @@ blit2d_bind_src(struct radv_cmd_buffer 
>> *cmd_buffer,
>>           create_bview(cmd_buffer, src_buf, &tmp->bview, depth_format);
>>             radv_meta_push_descriptor_set(cmd_buffer, 
>> VK_PIPELINE_BIND_POINT_GRAPHICS,
>> - device->meta_state.blit2d.p_layouts[src_type],
>> + device->meta_state.blit2d[log2_samples].p_layouts[src_type],
>>                             0, /* set */
>>                             1, /* descriptorWriteCount */
>>                             (VkWriteDescriptorSet[]) {
>> @@ -123,7 +124,7 @@ blit2d_bind_src(struct radv_cmd_buffer *cmd_buffer,
>>                             });
>> radv_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer),
>> - device->meta_state.blit2d.p_layouts[src_type],
>> + device->meta_state.blit2d[log2_samples].p_layouts[src_type],
>>                         VK_SHADER_STAGE_FRAGMENT_BIT, 16, 4,
>>                         &src_buf->pitch);
>>       } else {
>> @@ -131,12 +132,12 @@ blit2d_bind_src(struct radv_cmd_buffer 
>> *cmd_buffer,
>>             if (src_type == BLIT2D_SRC_TYPE_IMAGE_3D)
>> radv_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer),
>> - device->meta_state.blit2d.p_layouts[src_type],
>> + device->meta_state.blit2d[log2_samples].p_layouts[src_type],
>>                             VK_SHADER_STAGE_FRAGMENT_BIT, 16, 4,
>>                             &src_img->layer);
>>             radv_meta_push_descriptor_set(cmd_buffer, 
>> VK_PIPELINE_BIND_POINT_GRAPHICS,
>> - device->meta_state.blit2d.p_layouts[src_type],
>> + device->meta_state.blit2d[log2_samples].p_layouts[src_type],
>>                             0, /* set */
>>                             1, /* descriptorWriteCount */
>>                             (VkWriteDescriptorSet[]) {
>> @@ -190,10 +191,11 @@ blit2d_bind_dst(struct radv_cmd_buffer 
>> *cmd_buffer,
>>     static void
>>   bind_pipeline(struct radv_cmd_buffer *cmd_buffer,
>> -              enum blit2d_src_type src_type, unsigned fs_key)
>> +              enum blit2d_src_type src_type, unsigned fs_key,
>> +              uint32_t log2_samples)
>>   {
>>       VkPipeline pipeline =
>> - cmd_buffer->device->meta_state.blit2d.pipelines[src_type][fs_key];
>> + 
>> cmd_buffer->device->meta_state.blit2d[log2_samples].pipelines[src_type][fs_key];
>> radv_CmdBindPipeline(radv_cmd_buffer_to_handle(cmd_buffer),
>>                    VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
>> @@ -201,10 +203,11 @@ bind_pipeline(struct radv_cmd_buffer *cmd_buffer,
>>     static void
>>   bind_depth_pipeline(struct radv_cmd_buffer *cmd_buffer,
>> -            enum blit2d_src_type src_type)
>> +            enum blit2d_src_type src_type,
>> +            uint32_t log2_samples)
>>   {
>>       VkPipeline pipeline =
>> - cmd_buffer->device->meta_state.blit2d.depth_only_pipeline[src_type];
>> + 
>> cmd_buffer->device->meta_state.blit2d[log2_samples].depth_only_pipeline[src_type];
>> radv_CmdBindPipeline(radv_cmd_buffer_to_handle(cmd_buffer),
>>                    VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
>> @@ -212,10 +215,11 @@ bind_depth_pipeline(struct radv_cmd_buffer 
>> *cmd_buffer,
>>     static void
>>   bind_stencil_pipeline(struct radv_cmd_buffer *cmd_buffer,
>> -              enum blit2d_src_type src_type)
>> +              enum blit2d_src_type src_type,
>> +              uint32_t log2_samples)
>>   {
>>       VkPipeline pipeline =
>> - cmd_buffer->device->meta_state.blit2d.stencil_only_pipeline[src_type];
>> + 
>> cmd_buffer->device->meta_state.blit2d[log2_samples].stencil_only_pipeline[src_type];
>> radv_CmdBindPipeline(radv_cmd_buffer_to_handle(cmd_buffer),
>>                    VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
>> @@ -227,7 +231,8 @@ radv_meta_blit2d_normal_dst(struct 
>> radv_cmd_buffer *cmd_buffer,
>>                   struct radv_meta_blit2d_buffer *src_buf,
>>                   struct radv_meta_blit2d_surf *dst,
>>                   unsigned num_rects,
>> -                struct radv_meta_blit2d_rect *rects, enum 
>> blit2d_src_type src_type)
>> +                struct radv_meta_blit2d_rect *rects, enum 
>> blit2d_src_type src_type,
>> +                uint32_t log2_samples)
>>   {
>>       struct radv_device *device = cmd_buffer->device;
>>   @@ -241,7 +246,7 @@ radv_meta_blit2d_normal_dst(struct 
>> radv_cmd_buffer *cmd_buffer,
>>               else if (aspect_mask == VK_IMAGE_ASPECT_DEPTH_BIT)
>>                   depth_format = 
>> vk_format_depth_only(dst->image->vk_format);
>>               struct blit2d_src_temps src_temps;
>> -            blit2d_bind_src(cmd_buffer, src_img, src_buf, 
>> &src_temps, src_type, depth_format, aspect_mask);
>> +            blit2d_bind_src(cmd_buffer, src_img, src_buf, 
>> &src_temps, src_type, depth_format, aspect_mask, log2_samples);
>>                 struct blit2d_dst_temps dst_temps;
>>               blit2d_bind_dst(cmd_buffer, dst, rects[r].dst_x + 
>> rects[r].width,
>> @@ -255,7 +260,7 @@ radv_meta_blit2d_normal_dst(struct 
>> radv_cmd_buffer *cmd_buffer,
>>               };
>> radv_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer),
>> - device->meta_state.blit2d.p_layouts[src_type],
>> + device->meta_state.blit2d[log2_samples].p_layouts[src_type],
>>                       VK_SHADER_STAGE_VERTEX_BIT, 0, 16,
>>                       vertex_push_constants);
>>   @@ -266,7 +271,7 @@ radv_meta_blit2d_normal_dst(struct 
>> radv_cmd_buffer *cmd_buffer,
>> radv_CmdBeginRenderPass(radv_cmd_buffer_to_handle(cmd_buffer),
>>                               &(VkRenderPassBeginInfo) {
>>                                   .sType = 
>> VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
>> -                                    .renderPass = 
>> device->meta_state.blit2d.render_passes[fs_key][dst_layout],
>> +                                    .renderPass = 
>> device->meta_state.blit2d_render_passes[fs_key][dst_layout],
>>                                       .framebuffer = dst_temps.fb,
>>                                       .renderArea = {
>>                                       .offset = { rects[r].dst_x, 
>> rects[r].dst_y, },
>> @@ -277,13 +282,13 @@ radv_meta_blit2d_normal_dst(struct 
>> radv_cmd_buffer *cmd_buffer,
>>                                           }, 
>> VK_SUBPASS_CONTENTS_INLINE);
>>     -                bind_pipeline(cmd_buffer, src_type, fs_key);
>> +                bind_pipeline(cmd_buffer, src_type, fs_key, 
>> log2_samples);
>>               } else if (aspect_mask == VK_IMAGE_ASPECT_DEPTH_BIT) {
>>                   enum radv_blit_ds_layout ds_layout = 
>> radv_meta_blit_ds_to_type(dst->current_layout);
>> radv_CmdBeginRenderPass(radv_cmd_buffer_to_handle(cmd_buffer),
>>                               &(VkRenderPassBeginInfo) {
>>                                   .sType = 
>> VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
>> -                                    .renderPass = 
>> device->meta_state.blit2d.depth_only_rp[ds_layout],
>> +                                    .renderPass = 
>> device->meta_state.blit2d_depth_only_rp[ds_layout],
>>                                       .framebuffer = dst_temps.fb,
>>                                       .renderArea = {
>>                                       .offset = { rects[r].dst_x, 
>> rects[r].dst_y, },
>> @@ -294,14 +299,14 @@ radv_meta_blit2d_normal_dst(struct 
>> radv_cmd_buffer *cmd_buffer,
>>                                           }, 
>> VK_SUBPASS_CONTENTS_INLINE);
>>     -                bind_depth_pipeline(cmd_buffer, src_type);
>> +                bind_depth_pipeline(cmd_buffer, src_type, 
>> log2_samples);
>>                 } else if (aspect_mask == VK_IMAGE_ASPECT_STENCIL_BIT) {
>>                   enum radv_blit_ds_layout ds_layout = 
>> radv_meta_blit_ds_to_type(dst->current_layout);
>> radv_CmdBeginRenderPass(radv_cmd_buffer_to_handle(cmd_buffer),
>>                               &(VkRenderPassBeginInfo) {
>>                                   .sType = 
>> VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
>> -                                    .renderPass = 
>> device->meta_state.blit2d.stencil_only_rp[ds_layout],
>> +                                    .renderPass = 
>> device->meta_state.blit2d_stencil_only_rp[ds_layout],
>>                                       .framebuffer = dst_temps.fb,
>>                                       .renderArea = {
>>                                       .offset = { rects[r].dst_x, 
>> rects[r].dst_y, },
>> @@ -312,7 +317,7 @@ radv_meta_blit2d_normal_dst(struct 
>> radv_cmd_buffer *cmd_buffer,
>>                                           }, 
>> VK_SUBPASS_CONTENTS_INLINE);
>>     -                bind_stencil_pipeline(cmd_buffer, src_type);
>> +                bind_stencil_pipeline(cmd_buffer, src_type, 
>> log2_samples);
>>               } else
>>                   unreachable("Processing blit2d with multiple 
>> aspects.");
>>   @@ -332,7 +337,24 @@ radv_meta_blit2d_normal_dst(struct 
>> radv_cmd_buffer *cmd_buffer,
>>       - radv_CmdDraw(radv_cmd_buffer_to_handle(cmd_buffer), 3, 1, 0, 0);
>> +            if (log2_samples > 0) {
>> +                for (uint32_t sample = 0; sample < 
>> src_img->image->info.samples; sample++) {
>> +                    uint32_t sample_mask = 1 << sample;
>> + radv_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer),
>> + device->meta_state.blit2d[log2_samples].p_layouts[src_type],
>> +                                  VK_SHADER_STAGE_FRAGMENT_BIT, 20, 4,
>> +                                  &sample);
>> +
>> + radv_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer),
>> + device->meta_state.blit2d[log2_samples].p_layouts[src_type],
>> +                                  VK_SHADER_STAGE_FRAGMENT_BIT, 24, 4,
>> +                                  &sample_mask);
>> +
>> + radv_CmdDraw(radv_cmd_buffer_to_handle(cmd_buffer), 3, 1, 0, 0);
>> +                }
>> +            }
>> +            else
>> + radv_CmdDraw(radv_cmd_buffer_to_handle(cmd_buffer), 3, 1, 0, 0);
>> radv_CmdEndRenderPass(radv_cmd_buffer_to_handle(cmd_buffer));
>>                 /* At the point where we emit the draw call, all data 
>> from the
>> @@ -358,7 +380,8 @@ radv_meta_blit2d(struct radv_cmd_buffer *cmd_buffer,
>>       enum blit2d_src_type src_type = src_buf ? BLIT2D_SRC_TYPE_BUFFER :
>>           use_3d ? BLIT2D_SRC_TYPE_IMAGE_3D : BLIT2D_SRC_TYPE_IMAGE;
>>       radv_meta_blit2d_normal_dst(cmd_buffer, src_img, src_buf, dst,
>> -                    num_rects, rects, src_type);
>> +                    num_rects, rects, src_type,
>> +                    src_img ? 
>> util_logbase2(src_img->image->info.samples) : 0);
>>   }
>>     static nir_shader *
>> @@ -421,13 +444,14 @@ build_nir_vertex_shader(void)
>>     typedef nir_ssa_def* (*texel_fetch_build_func)(struct nir_builder *,
>>                                                  struct radv_device *,
>> -                                               nir_ssa_def *, bool);
>> +                                               nir_ssa_def *, bool, 
>> bool);
>>     static nir_ssa_def *
>>   build_nir_texel_fetch(struct nir_builder *b, struct radv_device 
>> *device,
>> -                      nir_ssa_def *tex_pos, bool is_3d)
>> +                      nir_ssa_def *tex_pos, bool is_3d, bool 
>> is_multisampled)
>>   {
>> -    enum glsl_sampler_dim dim = is_3d ? GLSL_SAMPLER_DIM_3D : 
>> GLSL_SAMPLER_DIM_2D;
>> +    enum glsl_sampler_dim dim =
>> +        is_3d ? GLSL_SAMPLER_DIM_3D : is_multisampled ? 
>> GLSL_SAMPLER_DIM_MS : GLSL_SAMPLER_DIM_2D;
>>       const struct glsl_type *sampler_type =
>>           glsl_sampler_type(dim, false, false, GLSL_TYPE_UINT);
>>       nir_variable *sampler = nir_variable_create(b->shader, 
>> nir_var_uniform,
>> @@ -436,6 +460,7 @@ build_nir_texel_fetch(struct nir_builder *b, 
>> struct radv_device *device,
>>       sampler->data.binding = 0;
>>         nir_ssa_def *tex_pos_3d = NULL;
>> +    nir_intrinsic_instr *sample_idx = NULL;
>>       if (is_3d) {
>>           nir_intrinsic_instr *layer = 
>> nir_intrinsic_instr_create(b->shader, nir_intrinsic_load_push_constant);
>>           nir_intrinsic_set_base(layer, 16);
>> @@ -451,13 +476,22 @@ build_nir_texel_fetch(struct nir_builder *b, 
>> struct radv_device *device,
>>           chans[2] = &layer->dest.ssa;
>>           tex_pos_3d = nir_vec(b, chans, 3);
>>       }
>> +    if (is_multisampled) {
>> +        sample_idx = nir_intrinsic_instr_create(b->shader, 
>> nir_intrinsic_load_push_constant);
>> +        nir_intrinsic_set_base(sample_idx, 20);
>> +        nir_intrinsic_set_range(sample_idx, 4);
>> +        sample_idx->src[0] = nir_src_for_ssa(nir_imm_int(b, 0));
>> +        sample_idx->num_components = 1;
>> +        nir_ssa_dest_init(&sample_idx->instr, &sample_idx->dest, 1, 
>> 32, "sample_idx");
>> +        nir_builder_instr_insert(b, &sample_idx->instr);
>> +    }
>>       nir_tex_instr *tex = nir_tex_instr_create(b->shader, 2);
>>       tex->sampler_dim = dim;
>> -    tex->op = nir_texop_txf;
>> +    tex->op = is_multisampled ? nir_texop_txf_ms : nir_texop_txf;
>>       tex->src[0].src_type = nir_tex_src_coord;
>>       tex->src[0].src = nir_src_for_ssa(is_3d ? tex_pos_3d : tex_pos);
>> -    tex->src[1].src_type = nir_tex_src_lod;
>> -    tex->src[1].src = nir_src_for_ssa(nir_imm_int(b, 0));
>> +    tex->src[1].src_type = is_multisampled ? nir_tex_src_ms_index : 
>> nir_tex_src_lod;
>> +    tex->src[1].src = nir_src_for_ssa(is_multisampled ? 
>> &sample_idx->dest.ssa : nir_imm_int(b, 0));
>>       tex->dest_type = nir_type_uint;
>>       tex->is_array = false;
>>       tex->coord_components = is_3d ? 3 : 2;
>> @@ -473,7 +507,7 @@ build_nir_texel_fetch(struct nir_builder *b, 
>> struct radv_device *device,
>>     static nir_ssa_def *
>>   build_nir_buffer_fetch(struct nir_builder *b, struct radv_device 
>> *device,
>> -               nir_ssa_def *tex_pos, bool is_3d)
>> +               nir_ssa_def *tex_pos, bool is_3d, bool is_multisampled)
>>   {
>>       const struct glsl_type *sampler_type =
>>           glsl_sampler_type(GLSL_SAMPLER_DIM_BUF, false, false, 
>> GLSL_TYPE_UINT);
>> @@ -519,9 +553,31 @@ static const 
>> VkPipelineVertexInputStateCreateInfo normal_vi_create_info = {
>>       .vertexAttributeDescriptionCount = 0,
>>   };
>>   +static void
>> +build_nir_store_sample_mask(struct nir_builder *b)
>> +{
>> +    nir_intrinsic_instr *sample_mask = 
>> nir_intrinsic_instr_create(b->shader, nir_intrinsic_load_push_constant);
>> +    nir_intrinsic_set_base(sample_mask, 24);
>> +    nir_intrinsic_set_range(sample_mask, 4);
>> +    sample_mask->src[0] = nir_src_for_ssa(nir_imm_int(b, 0));
>> +    sample_mask->num_components = 1;
>> +    nir_ssa_dest_init(&sample_mask->instr, &sample_mask->dest, 1, 
>> 32, "sample_mask");
>> +    nir_builder_instr_insert(b, &sample_mask->instr);
>> +
>> +    const struct glsl_type *sample_mask_out_type = glsl_uint_type();
>> +
>> +    nir_variable *sample_mask_out =
>> +        nir_variable_create(b->shader, nir_var_shader_out,
>> +                    sample_mask_out_type, "sample_mask_out");
>> +    sample_mask_out->data.location = FRAG_RESULT_SAMPLE_MASK;
>> +
>> +    nir_store_var(b, sample_mask_out, &sample_mask->dest.ssa, 0x1);
>> +}
>> +
>>   static nir_shader *
>>   build_nir_copy_fragment_shader(struct radv_device *device,
>> -                               texel_fetch_build_func txf_func, 
>> const char* name, bool is_3d)
>> +                               texel_fetch_build_func txf_func, 
>> const char* name, bool is_3d,
>> +                               bool is_multisampled)
>>   {
>>       const struct glsl_type *vec4 = glsl_vec4_type();
>>       const struct glsl_type *vec2 = 
>> glsl_vector_type(GLSL_TYPE_FLOAT, 2);
>> @@ -538,11 +594,15 @@ build_nir_copy_fragment_shader(struct 
>> radv_device *device,
>>                                 vec4, "f_color");
>>       color_out->data.location = FRAG_RESULT_DATA0;
>>   +    if (is_multisampled) {
>> +        build_nir_store_sample_mask(&b);
>> +    }
>> +
>>       nir_ssa_def *pos_int = nir_f2i32(&b, nir_load_var(&b, 
>> tex_pos_in));
>>       unsigned swiz[4] = { 0, 1 };
>>       nir_ssa_def *tex_pos = nir_swizzle(&b, pos_int, swiz, 2, false);
>>   -    nir_ssa_def *color = txf_func(&b, device, tex_pos, is_3d);
>> +    nir_ssa_def *color = txf_func(&b, device, tex_pos, is_3d, 
>> is_multisampled);
>>       nir_store_var(&b, color_out, color, 0xf);
>>         return b.shader;
>> @@ -550,7 +610,8 @@ build_nir_copy_fragment_shader(struct radv_device 
>> *device,
>>     static nir_shader *
>>   build_nir_copy_fragment_shader_depth(struct radv_device *device,
>> -                     texel_fetch_build_func txf_func, const char* 
>> name, bool is_3d)
>> +                     texel_fetch_build_func txf_func, const char* 
>> name, bool is_3d,
>> +                     bool is_multisampled)
>>   {
>>       const struct glsl_type *vec4 = glsl_vec4_type();
>>       const struct glsl_type *vec2 = 
>> glsl_vector_type(GLSL_TYPE_FLOAT, 2);
>> @@ -567,11 +628,15 @@ build_nir_copy_fragment_shader_depth(struct 
>> radv_device *device,
>>                                 vec4, "f_color");
>>       color_out->data.location = FRAG_RESULT_DEPTH;
>>   +    if (is_multisampled) {
>> +        build_nir_store_sample_mask(&b);
>> +    }
>> +
>>       nir_ssa_def *pos_int = nir_f2i32(&b, nir_load_var(&b, 
>> tex_pos_in));
>>       unsigned swiz[4] = { 0, 1 };
>>       nir_ssa_def *tex_pos = nir_swizzle(&b, pos_int, swiz, 2, false);
>>   -    nir_ssa_def *color = txf_func(&b, device, tex_pos, is_3d);
>> +    nir_ssa_def *color = txf_func(&b, device, tex_pos, is_3d, 
>> is_multisampled);
>>       nir_store_var(&b, color_out, color, 0x1);
>>         return b.shader;
>> @@ -579,7 +644,8 @@ build_nir_copy_fragment_shader_depth(struct 
>> radv_device *device,
>>     static nir_shader *
>>   build_nir_copy_fragment_shader_stencil(struct radv_device *device,
>> -                       texel_fetch_build_func txf_func, const char* 
>> name, bool is_3d)
>> +                       texel_fetch_build_func txf_func, const char* 
>> name, bool is_3d,
>> +                       bool is_multisampled)
>>   {
>>       const struct glsl_type *vec4 = glsl_vec4_type();
>>       const struct glsl_type *vec2 = 
>> glsl_vector_type(GLSL_TYPE_FLOAT, 2);
>> @@ -596,11 +662,15 @@ build_nir_copy_fragment_shader_stencil(struct 
>> radv_device *device,
>>                                 vec4, "f_color");
>>       color_out->data.location = FRAG_RESULT_STENCIL;
>>   +    if (is_multisampled) {
>> +        build_nir_store_sample_mask(&b);
>> +    }
>> +
>>       nir_ssa_def *pos_int = nir_f2i32(&b, nir_load_var(&b, 
>> tex_pos_in));
>>       unsigned swiz[4] = { 0, 1 };
>>       nir_ssa_def *tex_pos = nir_swizzle(&b, pos_int, swiz, 2, false);
>>   -    nir_ssa_def *color = txf_func(&b, device, tex_pos, is_3d);
>> +    nir_ssa_def *color = txf_func(&b, device, tex_pos, is_3d, 
>> is_multisampled);
>>       nir_store_var(&b, color_out, color, 0x1);
>>         return b.shader;
>> @@ -614,45 +684,48 @@ radv_device_finish_meta_blit2d_state(struct 
>> radv_device *device)
>>       for(unsigned j = 0; j < NUM_META_FS_KEYS; ++j) {
>>           for (unsigned k = 0; k < RADV_META_DST_LAYOUT_COUNT; ++k) {
>> radv_DestroyRenderPass(radv_device_to_handle(device),
>> - state->blit2d.render_passes[j][k],
>> -                                   &state->alloc);
>> + state->blit2d_render_passes[j][k],
>> +                           &state->alloc);
>>           }
>>       }
>>         for (enum radv_blit_ds_layout j = 
>> RADV_BLIT_DS_LAYOUT_TILE_ENABLE; j < RADV_BLIT_DS_LAYOUT_COUNT; j++) {
>>           radv_DestroyRenderPass(radv_device_to_handle(device),
>> -                       state->blit2d.depth_only_rp[j], &state->alloc);
>> +                       state->blit2d_depth_only_rp[j], &state->alloc);
>>           radv_DestroyRenderPass(radv_device_to_handle(device),
>> -                       state->blit2d.stencil_only_rp[j], 
>> &state->alloc);
>> +                       state->blit2d_stencil_only_rp[j], 
>> &state->alloc);
>>       }
>>   -    for (unsigned src = 0; src < BLIT2D_NUM_SRC_TYPES; src++) {
>> - radv_DestroyPipelineLayout(radv_device_to_handle(device),
>> -                       state->blit2d.p_layouts[src],
>> -                       &state->alloc);
>> - radv_DestroyDescriptorSetLayout(radv_device_to_handle(device),
>> -                        state->blit2d.ds_layouts[src],
>> -                        &state->alloc);
>> +    for (unsigned log2_samples = 0; log2_samples < 1 + 
>> MAX_SAMPLES_LOG2; ++log2_samples) {
>> +        for (unsigned src = 0; src < BLIT2D_NUM_SRC_TYPES; src++) {
>> + radv_DestroyPipelineLayout(radv_device_to_handle(device),
>> + state->blit2d[log2_samples].p_layouts[src],
>> +                           &state->alloc);
>> + radv_DestroyDescriptorSetLayout(radv_device_to_handle(device),
>> + state->blit2d[log2_samples].ds_layouts[src],
>> +                            &state->alloc);
>> +
>> +            for (unsigned j = 0; j < NUM_META_FS_KEYS; ++j) {
>> + radv_DestroyPipeline(radv_device_to_handle(device),
>> + state->blit2d[log2_samples].pipelines[src][j],
>> +                             &state->alloc);
>> +            }
>>   -        for (unsigned j = 0; j < NUM_META_FS_KEYS; ++j) {
>> radv_DestroyPipeline(radv_device_to_handle(device),
>> -                         state->blit2d.pipelines[src][j],
>> + state->blit2d[log2_samples].depth_only_pipeline[src],
>> +                         &state->alloc);
>> +            radv_DestroyPipeline(radv_device_to_handle(device),
>> + state->blit2d[log2_samples].stencil_only_pipeline[src],
>>                            &state->alloc);
>>           }
>> -
>> -        radv_DestroyPipeline(radv_device_to_handle(device),
>> -                     state->blit2d.depth_only_pipeline[src],
>> -                     &state->alloc);
>> -        radv_DestroyPipeline(radv_device_to_handle(device),
>> - state->blit2d.stencil_only_pipeline[src],
>> -                     &state->alloc);
>>       }
>>   }
>>     static VkResult
>>   blit2d_init_color_pipeline(struct radv_device *device,
>>                  enum blit2d_src_type src_type,
>> -               VkFormat format)
>> +               VkFormat format,
>> +               uint32_t log2_samples)
>>   {
>>       VkResult result;
>>       unsigned fs_key = radv_format_meta_fs_key(format);
>> @@ -681,7 +754,7 @@ blit2d_init_color_pipeline(struct radv_device 
>> *device,
>>       struct radv_shader_module fs = { .nir = NULL };
>>     -    fs.nir = build_nir_copy_fragment_shader(device, src_func, 
>> name, src_type == BLIT2D_SRC_TYPE_IMAGE_3D);
>> +    fs.nir = build_nir_copy_fragment_shader(device, src_func, name, 
>> src_type == BLIT2D_SRC_TYPE_IMAGE_3D, log2_samples > 0);
>>       vi_create_info = &normal_vi_create_info;
>>         struct radv_shader_module vs = {
>> @@ -705,7 +778,7 @@ blit2d_init_color_pipeline(struct radv_device 
>> *device,
>>       };
>>         for (unsigned dst_layout = 0; dst_layout < 
>> RADV_META_DST_LAYOUT_COUNT; ++dst_layout) {
>> -        if 
>> (!device->meta_state.blit2d.render_passes[fs_key][dst_layout]) {
>> +        if 
>> (!device->meta_state.blit2d_render_passes[fs_key][dst_layout]) {
>>               VkImageLayout layout = 
>> radv_meta_dst_layout_to_layout(dst_layout);
>>                 result = 
>> radv_CreateRenderPass(radv_device_to_handle(device),
>> @@ -737,7 +810,7 @@ blit2d_init_color_pipeline(struct radv_device 
>> *device,
>>                           .pPreserveAttachments = (uint32_t[]) { 0 },
>>                           },
>>                           .dependencyCount = 0,
>> -                    }, &device->meta_state.alloc, 
>> &device->meta_state.blit2d.render_passes[fs_key][dst_layout]);
>> +                    }, &device->meta_state.alloc, 
>> &device->meta_state.blit2d_render_passes[fs_key][dst_layout]);
>>           }
>>       }
>>   @@ -765,7 +838,7 @@ blit2d_init_color_pipeline(struct radv_device 
>> *device,
>>           },
>>           .pMultisampleState = &(VkPipelineMultisampleStateCreateInfo) {
>>               .sType = 
>> VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
>> -            .rasterizationSamples = 1,
>> +            .rasterizationSamples = 1 << log2_samples,
>>               .sampleShadingEnable = false,
>>               .pSampleMask = (VkSampleMask[]) { UINT32_MAX },
>>           },
>> @@ -796,8 +869,8 @@ blit2d_init_color_pipeline(struct radv_device 
>> *device,
>>               },
>>           },
>>           .flags = 0,
>> -        .layout = device->meta_state.blit2d.p_layouts[src_type],
>> -        .renderPass = 
>> device->meta_state.blit2d.render_passes[fs_key][0],
>> +        .layout = 
>> device->meta_state.blit2d[log2_samples].p_layouts[src_type],
>> +        .renderPass = 
>> device->meta_state.blit2d_render_passes[fs_key][0],
>>           .subpass = 0,
>>       };
>>   @@ -809,7 +882,7 @@ blit2d_init_color_pipeline(struct radv_device 
>> *device,
>> radv_pipeline_cache_to_handle(&device->meta_state.cache),
>>                              &vk_pipeline_info, &radv_pipeline_info,
>>                              &device->meta_state.alloc,
>> - &device->meta_state.blit2d.pipelines[src_type][fs_key]);
>> + &device->meta_state.blit2d[log2_samples].pipelines[src_type][fs_key]);
>>           ralloc_free(vs.nir);
>> @@ -820,7 +893,8 @@ blit2d_init_color_pipeline(struct radv_device 
>> *device,
>>     static VkResult
>>   blit2d_init_depth_only_pipeline(struct radv_device *device,
>> -                enum blit2d_src_type src_type)
>> +                enum blit2d_src_type src_type,
>> +                uint32_t log2_samples)
>>   {
>>       VkResult result;
>>       const char *name;
>> @@ -847,7 +921,7 @@ blit2d_init_depth_only_pipeline(struct 
>> radv_device *device,
>>       const VkPipelineVertexInputStateCreateInfo *vi_create_info;
>>       struct radv_shader_module fs = { .nir = NULL };
>>   -    fs.nir = build_nir_copy_fragment_shader_depth(device, 
>> src_func, name, src_type == BLIT2D_SRC_TYPE_IMAGE_3D);
>> +    fs.nir = build_nir_copy_fragment_shader_depth(device, src_func, 
>> name, src_type == BLIT2D_SRC_TYPE_IMAGE_3D, log2_samples > 0);
>>       vi_create_info = &normal_vi_create_info;
>>         struct radv_shader_module vs = {
>> @@ -871,7 +945,7 @@ blit2d_init_depth_only_pipeline(struct 
>> radv_device *device,
>>       };
>>         for (enum radv_blit_ds_layout ds_layout = 
>> RADV_BLIT_DS_LAYOUT_TILE_ENABLE; ds_layout < 
>> RADV_BLIT_DS_LAYOUT_COUNT; ds_layout++) {
>> -        if (!device->meta_state.blit2d.depth_only_rp[ds_layout]) {
>> +        if (!device->meta_state.blit2d_depth_only_rp[ds_layout]) {
>>               VkImageLayout layout = 
>> radv_meta_blit_ds_to_layout(ds_layout);
>>               result = 
>> radv_CreateRenderPass(radv_device_to_handle(device),
>>                                  &(VkRenderPassCreateInfo) {
>> @@ -899,7 +973,7 @@ blit2d_init_depth_only_pipeline(struct 
>> radv_device *device,
>>                                          .pPreserveAttachments = 
>> (uint32_t[]) { 0 },
>>                                      },
>>                                      .dependencyCount = 0,
>> -                            }, &device->meta_state.alloc, 
>> &device->meta_state.blit2d.depth_only_rp[ds_layout]);
>> +                            }, &device->meta_state.alloc, 
>> &device->meta_state.blit2d_depth_only_rp[ds_layout]);
>>           }
>>       }
>>   @@ -927,7 +1001,7 @@ blit2d_init_depth_only_pipeline(struct 
>> radv_device *device,
>>           },
>>           .pMultisampleState = &(VkPipelineMultisampleStateCreateInfo) {
>>               .sType = 
>> VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
>> -            .rasterizationSamples = 1,
>> +            .rasterizationSamples = 1 << log2_samples,
>>               .sampleShadingEnable = false,
>>               .pSampleMask = (VkSampleMask[]) { UINT32_MAX },
>>           },
>> @@ -958,8 +1032,8 @@ blit2d_init_depth_only_pipeline(struct 
>> radv_device *device,
>>               },
>>           },
>>           .flags = 0,
>> -        .layout = device->meta_state.blit2d.p_layouts[src_type],
>> -        .renderPass = device->meta_state.blit2d.depth_only_rp[0],
>> +        .layout = 
>> device->meta_state.blit2d[log2_samples].p_layouts[src_type],
>> +        .renderPass = device->meta_state.blit2d_depth_only_rp[0],
>>           .subpass = 0,
>>       };
>>   @@ -971,7 +1045,7 @@ blit2d_init_depth_only_pipeline(struct 
>> radv_device *device,
>> radv_pipeline_cache_to_handle(&device->meta_state.cache),
>>                              &vk_pipeline_info, &radv_pipeline_info,
>>                              &device->meta_state.alloc,
>> - &device->meta_state.blit2d.depth_only_pipeline[src_type]);
>> + 
>> &device->meta_state.blit2d[log2_samples].depth_only_pipeline[src_type]);
>>           ralloc_free(vs.nir);
>> @@ -982,7 +1056,8 @@ blit2d_init_depth_only_pipeline(struct 
>> radv_device *device,
>>     static VkResult
>>   blit2d_init_stencil_only_pipeline(struct radv_device *device,
>> -                  enum blit2d_src_type src_type)
>> +                  enum blit2d_src_type src_type,
>> +                  uint32_t log2_samples)
>>   {
>>       VkResult result;
>>       const char *name;
>> @@ -1009,7 +1084,7 @@ blit2d_init_stencil_only_pipeline(struct 
>> radv_device *device,
>>       const VkPipelineVertexInputStateCreateInfo *vi_create_info;
>>       struct radv_shader_module fs = { .nir = NULL };
>>   -    fs.nir = build_nir_copy_fragment_shader_stencil(device, 
>> src_func, name, src_type == BLIT2D_SRC_TYPE_IMAGE_3D);
>> +    fs.nir = build_nir_copy_fragment_shader_stencil(device, 
>> src_func, name, src_type == BLIT2D_SRC_TYPE_IMAGE_3D, log2_samples > 0);
>>       vi_create_info = &normal_vi_create_info;
>>         struct radv_shader_module vs = {
>> @@ -1033,7 +1108,7 @@ blit2d_init_stencil_only_pipeline(struct 
>> radv_device *device,
>>       };
>>         for (enum radv_blit_ds_layout ds_layout = 
>> RADV_BLIT_DS_LAYOUT_TILE_ENABLE; ds_layout < 
>> RADV_BLIT_DS_LAYOUT_COUNT; ds_layout++) {
>> -        if (!device->meta_state.blit2d.stencil_only_rp[ds_layout]) {
>> +        if (!device->meta_state.blit2d_stencil_only_rp[ds_layout]) {
>>               VkImageLayout layout = 
>> radv_meta_blit_ds_to_layout(ds_layout);
>>               result = 
>> radv_CreateRenderPass(radv_device_to_handle(device),
>>                                  &(VkRenderPassCreateInfo) {
>> @@ -1061,7 +1136,7 @@ blit2d_init_stencil_only_pipeline(struct 
>> radv_device *device,
>>                                          .pPreserveAttachments = 
>> (uint32_t[]) { 0 },
>>                                      },
>>                                      .dependencyCount = 0,
>> -                               }, &device->meta_state.alloc, 
>> &device->meta_state.blit2d.stencil_only_rp[ds_layout]);
>> +                               }, &device->meta_state.alloc, 
>> &device->meta_state.blit2d_stencil_only_rp[ds_layout]);
>>           }
>>       }
>>   @@ -1089,7 +1164,7 @@ blit2d_init_stencil_only_pipeline(struct 
>> radv_device *device,
>>           },
>>           .pMultisampleState = &(VkPipelineMultisampleStateCreateInfo) {
>>               .sType = 
>> VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
>> -            .rasterizationSamples = 1,
>> +            .rasterizationSamples = 1 << log2_samples,
>>               .sampleShadingEnable = false,
>>               .pSampleMask = (VkSampleMask[]) { UINT32_MAX },
>>           },
>> @@ -1136,8 +1211,8 @@ blit2d_init_stencil_only_pipeline(struct 
>> radv_device *device,
>>               },
>>           },
>>           .flags = 0,
>> -        .layout = device->meta_state.blit2d.p_layouts[src_type],
>> -        .renderPass = device->meta_state.blit2d.stencil_only_rp[0],
>> +        .layout = 
>> device->meta_state.blit2d[log2_samples].p_layouts[src_type],
>> +        .renderPass = device->meta_state.blit2d_stencil_only_rp[0],
>>           .subpass = 0,
>>       };
>>   @@ -1149,7 +1224,7 @@ blit2d_init_stencil_only_pipeline(struct 
>> radv_device *device,
>> radv_pipeline_cache_to_handle(&device->meta_state.cache),
>>                              &vk_pipeline_info, &radv_pipeline_info,
>>                              &device->meta_state.alloc,
>> - &device->meta_state.blit2d.stencil_only_pipeline[src_type]);
>> + 
>> &device->meta_state.blit2d[log2_samples].stencil_only_pipeline[src_type]);
>>           ralloc_free(vs.nir);
>> @@ -1175,15 +1250,16 @@ static VkFormat pipeline_formats[] = {
>>     static VkResult
>>   meta_blit2d_create_pipe_layout(struct radv_device *device,
>> -                   int idx)
>> +                   int idx,
>> +                   uint32_t log2_samples)
>>   {
>>       VkResult result;
>>       VkDescriptorType desc_type = (idx == BLIT2D_SRC_TYPE_BUFFER) ? 
>> VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER : 
>> VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
>>       const VkPushConstantRange push_constant_ranges[] = {
>>           {VK_SHADER_STAGE_VERTEX_BIT, 0, 16},
>> -        {VK_SHADER_STAGE_FRAGMENT_BIT, 16, 4},
>> +        {VK_SHADER_STAGE_FRAGMENT_BIT, 16, 12},
>>       };
>> -    int num_push_constant_range = (idx != BLIT2D_SRC_TYPE_IMAGE) ? 2 
>> : 1;
>> +    int num_push_constant_range = (idx != BLIT2D_SRC_TYPE_IMAGE || 
>> log2_samples > 0) ? 2 : 1;
>>         result = 
>> radv_CreateDescriptorSetLayout(radv_device_to_handle(device),
>>                           &(VkDescriptorSetLayoutCreateInfo) {
>> @@ -1199,7 +1275,7 @@ meta_blit2d_create_pipe_layout(struct 
>> radv_device *device,
>>                                   .pImmutableSamplers = NULL
>>                               },
>>                               }
>> -                        }, &device->meta_state.alloc, 
>> &device->meta_state.blit2d.ds_layouts[idx]);
>> +                        }, &device->meta_state.alloc, 
>> &device->meta_state.blit2d[log2_samples].ds_layouts[idx]);
>>       if (result != VK_SUCCESS)
>>           goto fail;
>>   @@ -1207,11 +1283,11 @@ meta_blit2d_create_pipe_layout(struct 
>> radv_device *device,
>>                          &(VkPipelineLayoutCreateInfo) {
>>                              .sType = 
>> VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
>>                                  .setLayoutCount = 1,
>> -                               .pSetLayouts = 
>> &device->meta_state.blit2d.ds_layouts[idx],
>> +                               .pSetLayouts = 
>> &device->meta_state.blit2d[log2_samples].ds_layouts[idx],
>>                                  .pushConstantRangeCount = 
>> num_push_constant_range,
>>                                  .pPushConstantRanges = 
>> push_constant_ranges,
>>                                  },
>> -                       &device->meta_state.alloc, 
>> &device->meta_state.blit2d.p_layouts[idx]);
>> +                       &device->meta_state.alloc, 
>> &device->meta_state.blit2d[log2_samples].p_layouts[idx]);
>>       if (result != VK_SUCCESS)
>>           goto fail;
>>       return VK_SUCCESS;
>> @@ -1225,27 +1301,33 @@ radv_device_init_meta_blit2d_state(struct 
>> radv_device *device)
>>       VkResult result;
>>       bool create_3d = device->physical_device->rad_info.chip_class 
>> >= GFX9;
>>   -    for (unsigned src = 0; src < BLIT2D_NUM_SRC_TYPES; src++) {
>> -        if (src == BLIT2D_SRC_TYPE_IMAGE_3D && !create_3d)
>> -            continue;
>> +    for (unsigned log2_samples = 0; log2_samples < 1 + 
>> MAX_SAMPLES_LOG2; log2_samples++) {
>> +        for (unsigned src = 0; src < BLIT2D_NUM_SRC_TYPES; src++) {
>> +            if (src == BLIT2D_SRC_TYPE_IMAGE_3D && !create_3d)
>> +                continue;
>>   -        result = meta_blit2d_create_pipe_layout(device, src);
>> -        if (result != VK_SUCCESS)
>> -            goto fail;
>> +            /* Don't need to handle copies between buffers and 
>> multisample images. */
>> +            if (src == BLIT2D_SRC_TYPE_BUFFER && log2_samples > 0)
>> +                continue;
>>   -        for (unsigned j = 0; j < ARRAY_SIZE(pipeline_formats); ++j) {
>> -            result = blit2d_init_color_pipeline(device, src, 
>> pipeline_formats[j]);
>> +            result = meta_blit2d_create_pipe_layout(device, src, 
>> log2_samples);
>>               if (result != VK_SUCCESS)
>>                   goto fail;
>> -        }
>>   -        result = blit2d_init_depth_only_pipeline(device, src);
>> -        if (result != VK_SUCCESS)
>> -            goto fail;
>> +            for (unsigned j = 0; j < ARRAY_SIZE(pipeline_formats); 
>> ++j) {
>> +                result = blit2d_init_color_pipeline(device, src, 
>> pipeline_formats[j], log2_samples);
>> +                if (result != VK_SUCCESS)
>> +                    goto fail;
>> +            }
>> +
>> +            result = blit2d_init_depth_only_pipeline(device, src, 
>> log2_samples);
>> +            if (result != VK_SUCCESS)
>> +                goto fail;
>>   -        result = blit2d_init_stencil_only_pipeline(device, src);
>> -        if (result != VK_SUCCESS)
>> -            goto fail;
>> +            result = blit2d_init_stencil_only_pipeline(device, src, 
>> log2_samples);
>> +            if (result != VK_SUCCESS)
>> +                goto fail;
>> +        }
>>       }
>>         return VK_SUCCESS;
>> diff --git a/src/amd/vulkan/radv_private.h 
>> b/src/amd/vulkan/radv_private.h
>> index 883342ede88..5d67271961b 100644
>> --- a/src/amd/vulkan/radv_private.h
>> +++ b/src/amd/vulkan/radv_private.h
>> @@ -465,18 +465,18 @@ struct radv_meta_state {
>>       } blit;
>>         struct {
>> -        VkRenderPass 
>> render_passes[NUM_META_FS_KEYS][RADV_META_DST_LAYOUT_COUNT];
>> +        VkPipelineLayout p_layouts[5];
>> +        VkDescriptorSetLayout ds_layouts[5];
>> +        VkPipeline pipelines[5][NUM_META_FS_KEYS];
>>   -        VkPipelineLayout p_layouts[3];
>> -        VkDescriptorSetLayout ds_layouts[3];
>> -        VkPipeline pipelines[3][NUM_META_FS_KEYS];
>> +        VkPipeline depth_only_pipeline[5];
>>   -        VkRenderPass depth_only_rp[RADV_BLIT_DS_LAYOUT_COUNT];
>> -        VkPipeline depth_only_pipeline[3];
>> +        VkPipeline stencil_only_pipeline[5];
>> +    } blit2d[1 + MAX_SAMPLES_LOG2];
>>   -        VkRenderPass stencil_only_rp[RADV_BLIT_DS_LAYOUT_COUNT];
>> -        VkPipeline stencil_only_pipeline[3];
>> -    } blit2d;
>> +    VkRenderPass 
>> blit2d_render_passes[NUM_META_FS_KEYS][RADV_META_DST_LAYOUT_COUNT];
>> +    VkRenderPass blit2d_depth_only_rp[RADV_BLIT_DS_LAYOUT_COUNT];
>> +    VkRenderPass blit2d_stencil_only_rp[RADV_BLIT_DS_LAYOUT_COUNT];
>>         struct {
>>           VkPipelineLayout img_p_layout;
>>
On 04/27/2018 02:30 PM, Matthew Nicholls wrote:
> I've verified the V2 of my patch does still fix the original issue I was 
> seeing.
> 
> Thanks a bunch.

Cool! Thanks for confirming, I will push the patch.

> 
> Matthew.
> 
> 
> On 27/04/18 12:26, Samuel Pitoiset wrote:
>> Matthew, can you double-check if v2 still fixes the issue for you? 
>> Thanks!
>>
>> On 04/27/2018 01:23 PM, Samuel Pitoiset wrote:
>>> From: Matthew Nicholls <mnicholls@feralinteractive.com>
>>>
>>> Previously before fb077b0728, the LOD parameter was being used in 
>>> place of the
>>> sample index, which would only copy the first sample to all samples 
>>> in the
>>> destination image. After that multisample image copies wouldn't copy 
>>> anything
>>> from my observations.
>>>
>>> This fixes some copy_and_blit CTS tests.
>>>
>>> v2: - use GLSL_SAMPLER_DIM_MS instead of 2D (Samuel)
>>>      - updated commit description (Samuel)
>>>
>>> Fix this properly by copying each sample in a separate radv_CmdDraw 
>>> and using a
>>> pipeline with the correct rasterizationSamples for the destination 
>>> image.
>>>
>>> Cc: 18.0 18.1 <mesa-stable@lists.freedesktop.org>
>>> ---
>>>   src/amd/vulkan/radv_meta_blit2d.c | 282 +++++++++++++++++++-----------
>>>   src/amd/vulkan/radv_private.h     |  18 +-
>>>   2 files changed, 191 insertions(+), 109 deletions(-)
>>>
>>> diff --git a/src/amd/vulkan/radv_meta_blit2d.c 
>>> b/src/amd/vulkan/radv_meta_blit2d.c
>>> index e163056257e..3ad032f5989 100644
>>> --- a/src/amd/vulkan/radv_meta_blit2d.c
>>> +++ b/src/amd/vulkan/radv_meta_blit2d.c
>>> @@ -100,7 +100,8 @@ blit2d_bind_src(struct radv_cmd_buffer *cmd_buffer,
>>>                   struct radv_meta_blit2d_buffer *src_buf,
>>>                   struct blit2d_src_temps *tmp,
>>>                   enum blit2d_src_type src_type, VkFormat depth_format,
>>> -                VkImageAspectFlagBits aspects)
>>> +                VkImageAspectFlagBits aspects,
>>> +                uint32_t log2_samples)
>>>   {
>>>       struct radv_device *device = cmd_buffer->device;
>>>   @@ -108,7 +109,7 @@ blit2d_bind_src(struct radv_cmd_buffer 
>>> *cmd_buffer,
>>>           create_bview(cmd_buffer, src_buf, &tmp->bview, depth_format);
>>>             radv_meta_push_descriptor_set(cmd_buffer, 
>>> VK_PIPELINE_BIND_POINT_GRAPHICS,
>>> - device->meta_state.blit2d.p_layouts[src_type],
>>> + device->meta_state.blit2d[log2_samples].p_layouts[src_type],
>>>                             0, /* set */
>>>                             1, /* descriptorWriteCount */
>>>                             (VkWriteDescriptorSet[]) {
>>> @@ -123,7 +124,7 @@ blit2d_bind_src(struct radv_cmd_buffer *cmd_buffer,
>>>                             });
>>> radv_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer),
>>> - device->meta_state.blit2d.p_layouts[src_type],
>>> + device->meta_state.blit2d[log2_samples].p_layouts[src_type],
>>>                         VK_SHADER_STAGE_FRAGMENT_BIT, 16, 4,
>>>                         &src_buf->pitch);
>>>       } else {
>>> @@ -131,12 +132,12 @@ blit2d_bind_src(struct radv_cmd_buffer 
>>> *cmd_buffer,
>>>             if (src_type == BLIT2D_SRC_TYPE_IMAGE_3D)
>>> radv_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer),
>>> - device->meta_state.blit2d.p_layouts[src_type],
>>> + device->meta_state.blit2d[log2_samples].p_layouts[src_type],
>>>                             VK_SHADER_STAGE_FRAGMENT_BIT, 16, 4,
>>>                             &src_img->layer);
>>>             radv_meta_push_descriptor_set(cmd_buffer, 
>>> VK_PIPELINE_BIND_POINT_GRAPHICS,
>>> - device->meta_state.blit2d.p_layouts[src_type],
>>> + device->meta_state.blit2d[log2_samples].p_layouts[src_type],
>>>                             0, /* set */
>>>                             1, /* descriptorWriteCount */
>>>                             (VkWriteDescriptorSet[]) {
>>> @@ -190,10 +191,11 @@ blit2d_bind_dst(struct radv_cmd_buffer 
>>> *cmd_buffer,
>>>     static void
>>>   bind_pipeline(struct radv_cmd_buffer *cmd_buffer,
>>> -              enum blit2d_src_type src_type, unsigned fs_key)
>>> +              enum blit2d_src_type src_type, unsigned fs_key,
>>> +              uint32_t log2_samples)
>>>   {
>>>       VkPipeline pipeline =
>>> - cmd_buffer->device->meta_state.blit2d.pipelines[src_type][fs_key];
>>> + 
>>> cmd_buffer->device->meta_state.blit2d[log2_samples].pipelines[src_type][fs_key]; 
>>>
>>> radv_CmdBindPipeline(radv_cmd_buffer_to_handle(cmd_buffer),
>>>                    VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
>>> @@ -201,10 +203,11 @@ bind_pipeline(struct radv_cmd_buffer *cmd_buffer,
>>>     static void
>>>   bind_depth_pipeline(struct radv_cmd_buffer *cmd_buffer,
>>> -            enum blit2d_src_type src_type)
>>> +            enum blit2d_src_type src_type,
>>> +            uint32_t log2_samples)
>>>   {
>>>       VkPipeline pipeline =
>>> - cmd_buffer->device->meta_state.blit2d.depth_only_pipeline[src_type];
>>> + 
>>> cmd_buffer->device->meta_state.blit2d[log2_samples].depth_only_pipeline[src_type]; 
>>>
>>> radv_CmdBindPipeline(radv_cmd_buffer_to_handle(cmd_buffer),
>>>                    VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
>>> @@ -212,10 +215,11 @@ bind_depth_pipeline(struct radv_cmd_buffer 
>>> *cmd_buffer,
>>>     static void
>>>   bind_stencil_pipeline(struct radv_cmd_buffer *cmd_buffer,
>>> -              enum blit2d_src_type src_type)
>>> +              enum blit2d_src_type src_type,
>>> +              uint32_t log2_samples)
>>>   {
>>>       VkPipeline pipeline =
>>> - cmd_buffer->device->meta_state.blit2d.stencil_only_pipeline[src_type];
>>> + 
>>> cmd_buffer->device->meta_state.blit2d[log2_samples].stencil_only_pipeline[src_type]; 
>>>
>>> radv_CmdBindPipeline(radv_cmd_buffer_to_handle(cmd_buffer),
>>>                    VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
>>> @@ -227,7 +231,8 @@ radv_meta_blit2d_normal_dst(struct 
>>> radv_cmd_buffer *cmd_buffer,
>>>                   struct radv_meta_blit2d_buffer *src_buf,
>>>                   struct radv_meta_blit2d_surf *dst,
>>>                   unsigned num_rects,
>>> -                struct radv_meta_blit2d_rect *rects, enum 
>>> blit2d_src_type src_type)
>>> +                struct radv_meta_blit2d_rect *rects, enum 
>>> blit2d_src_type src_type,
>>> +                uint32_t log2_samples)
>>>   {
>>>       struct radv_device *device = cmd_buffer->device;
>>>   @@ -241,7 +246,7 @@ radv_meta_blit2d_normal_dst(struct 
>>> radv_cmd_buffer *cmd_buffer,
>>>               else if (aspect_mask == VK_IMAGE_ASPECT_DEPTH_BIT)
>>>                   depth_format = 
>>> vk_format_depth_only(dst->image->vk_format);
>>>               struct blit2d_src_temps src_temps;
>>> -            blit2d_bind_src(cmd_buffer, src_img, src_buf, 
>>> &src_temps, src_type, depth_format, aspect_mask);
>>> +            blit2d_bind_src(cmd_buffer, src_img, src_buf, 
>>> &src_temps, src_type, depth_format, aspect_mask, log2_samples);
>>>                 struct blit2d_dst_temps dst_temps;
>>>               blit2d_bind_dst(cmd_buffer, dst, rects[r].dst_x + 
>>> rects[r].width,
>>> @@ -255,7 +260,7 @@ radv_meta_blit2d_normal_dst(struct 
>>> radv_cmd_buffer *cmd_buffer,
>>>               };
>>> radv_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer),
>>> - device->meta_state.blit2d.p_layouts[src_type],
>>> + device->meta_state.blit2d[log2_samples].p_layouts[src_type],
>>>                       VK_SHADER_STAGE_VERTEX_BIT, 0, 16,
>>>                       vertex_push_constants);
>>>   @@ -266,7 +271,7 @@ radv_meta_blit2d_normal_dst(struct 
>>> radv_cmd_buffer *cmd_buffer,
>>> radv_CmdBeginRenderPass(radv_cmd_buffer_to_handle(cmd_buffer),
>>>                               &(VkRenderPassBeginInfo) {
>>>                                   .sType = 
>>> VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
>>> -                                    .renderPass = 
>>> device->meta_state.blit2d.render_passes[fs_key][dst_layout],
>>> +                                    .renderPass = 
>>> device->meta_state.blit2d_render_passes[fs_key][dst_layout],
>>>                                       .framebuffer = dst_temps.fb,
>>>                                       .renderArea = {
>>>                                       .offset = { rects[r].dst_x, 
>>> rects[r].dst_y, },
>>> @@ -277,13 +282,13 @@ radv_meta_blit2d_normal_dst(struct 
>>> radv_cmd_buffer *cmd_buffer,
>>>                                           }, 
>>> VK_SUBPASS_CONTENTS_INLINE);
>>>     -                bind_pipeline(cmd_buffer, src_type, fs_key);
>>> +                bind_pipeline(cmd_buffer, src_type, fs_key, 
>>> log2_samples);
>>>               } else if (aspect_mask == VK_IMAGE_ASPECT_DEPTH_BIT) {
>>>                   enum radv_blit_ds_layout ds_layout = 
>>> radv_meta_blit_ds_to_type(dst->current_layout);
>>> radv_CmdBeginRenderPass(radv_cmd_buffer_to_handle(cmd_buffer),
>>>                               &(VkRenderPassBeginInfo) {
>>>                                   .sType = 
>>> VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
>>> -                                    .renderPass = 
>>> device->meta_state.blit2d.depth_only_rp[ds_layout],
>>> +                                    .renderPass = 
>>> device->meta_state.blit2d_depth_only_rp[ds_layout],
>>>                                       .framebuffer = dst_temps.fb,
>>>                                       .renderArea = {
>>>                                       .offset = { rects[r].dst_x, 
>>> rects[r].dst_y, },
>>> @@ -294,14 +299,14 @@ radv_meta_blit2d_normal_dst(struct 
>>> radv_cmd_buffer *cmd_buffer,
>>>                                           }, 
>>> VK_SUBPASS_CONTENTS_INLINE);
>>>     -                bind_depth_pipeline(cmd_buffer, src_type);
>>> +                bind_depth_pipeline(cmd_buffer, src_type, 
>>> log2_samples);
>>>                 } else if (aspect_mask == VK_IMAGE_ASPECT_STENCIL_BIT) {
>>>                   enum radv_blit_ds_layout ds_layout = 
>>> radv_meta_blit_ds_to_type(dst->current_layout);
>>> radv_CmdBeginRenderPass(radv_cmd_buffer_to_handle(cmd_buffer),
>>>                               &(VkRenderPassBeginInfo) {
>>>                                   .sType = 
>>> VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
>>> -                                    .renderPass = 
>>> device->meta_state.blit2d.stencil_only_rp[ds_layout],
>>> +                                    .renderPass = 
>>> device->meta_state.blit2d_stencil_only_rp[ds_layout],
>>>                                       .framebuffer = dst_temps.fb,
>>>                                       .renderArea = {
>>>                                       .offset = { rects[r].dst_x, 
>>> rects[r].dst_y, },
>>> @@ -312,7 +317,7 @@ radv_meta_blit2d_normal_dst(struct 
>>> radv_cmd_buffer *cmd_buffer,
>>>                                           }, 
>>> VK_SUBPASS_CONTENTS_INLINE);
>>>     -                bind_stencil_pipeline(cmd_buffer, src_type);
>>> +                bind_stencil_pipeline(cmd_buffer, src_type, 
>>> log2_samples);
>>>               } else
>>>                   unreachable("Processing blit2d with multiple 
>>> aspects.");
>>>   @@ -332,7 +337,24 @@ radv_meta_blit2d_normal_dst(struct 
>>> radv_cmd_buffer *cmd_buffer,
>>>       - radv_CmdDraw(radv_cmd_buffer_to_handle(cmd_buffer), 3, 1, 0, 0);
>>> +            if (log2_samples > 0) {
>>> +                for (uint32_t sample = 0; sample < 
>>> src_img->image->info.samples; sample++) {
>>> +                    uint32_t sample_mask = 1 << sample;
>>> + radv_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer),
>>> + device->meta_state.blit2d[log2_samples].p_layouts[src_type],
>>> +                                  VK_SHADER_STAGE_FRAGMENT_BIT, 20, 4,
>>> +                                  &sample);
>>> +
>>> + radv_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer),
>>> + device->meta_state.blit2d[log2_samples].p_layouts[src_type],
>>> +                                  VK_SHADER_STAGE_FRAGMENT_BIT, 24, 4,
>>> +                                  &sample_mask);
>>> +
>>> + radv_CmdDraw(radv_cmd_buffer_to_handle(cmd_buffer), 3, 1, 0, 0);
>>> +                }
>>> +            }
>>> +            else
>>> + radv_CmdDraw(radv_cmd_buffer_to_handle(cmd_buffer), 3, 1, 0, 0);
>>> radv_CmdEndRenderPass(radv_cmd_buffer_to_handle(cmd_buffer));
>>>                 /* At the point where we emit the draw call, all data 
>>> from the
>>> @@ -358,7 +380,8 @@ radv_meta_blit2d(struct radv_cmd_buffer *cmd_buffer,
>>>       enum blit2d_src_type src_type = src_buf ? BLIT2D_SRC_TYPE_BUFFER :
>>>           use_3d ? BLIT2D_SRC_TYPE_IMAGE_3D : BLIT2D_SRC_TYPE_IMAGE;
>>>       radv_meta_blit2d_normal_dst(cmd_buffer, src_img, src_buf, dst,
>>> -                    num_rects, rects, src_type);
>>> +                    num_rects, rects, src_type,
>>> +                    src_img ? 
>>> util_logbase2(src_img->image->info.samples) : 0);
>>>   }
>>>     static nir_shader *
>>> @@ -421,13 +444,14 @@ build_nir_vertex_shader(void)
>>>     typedef nir_ssa_def* (*texel_fetch_build_func)(struct nir_builder *,
>>>                                                  struct radv_device *,
>>> -                                               nir_ssa_def *, bool);
>>> +                                               nir_ssa_def *, bool, 
>>> bool);
>>>     static nir_ssa_def *
>>>   build_nir_texel_fetch(struct nir_builder *b, struct radv_device 
>>> *device,
>>> -                      nir_ssa_def *tex_pos, bool is_3d)
>>> +                      nir_ssa_def *tex_pos, bool is_3d, bool 
>>> is_multisampled)
>>>   {
>>> -    enum glsl_sampler_dim dim = is_3d ? GLSL_SAMPLER_DIM_3D : 
>>> GLSL_SAMPLER_DIM_2D;
>>> +    enum glsl_sampler_dim dim =
>>> +        is_3d ? GLSL_SAMPLER_DIM_3D : is_multisampled ? 
>>> GLSL_SAMPLER_DIM_MS : GLSL_SAMPLER_DIM_2D;
>>>       const struct glsl_type *sampler_type =
>>>           glsl_sampler_type(dim, false, false, GLSL_TYPE_UINT);
>>>       nir_variable *sampler = nir_variable_create(b->shader, 
>>> nir_var_uniform,
>>> @@ -436,6 +460,7 @@ build_nir_texel_fetch(struct nir_builder *b, 
>>> struct radv_device *device,
>>>       sampler->data.binding = 0;
>>>         nir_ssa_def *tex_pos_3d = NULL;
>>> +    nir_intrinsic_instr *sample_idx = NULL;
>>>       if (is_3d) {
>>>           nir_intrinsic_instr *layer = 
>>> nir_intrinsic_instr_create(b->shader, nir_intrinsic_load_push_constant);
>>>           nir_intrinsic_set_base(layer, 16);
>>> @@ -451,13 +476,22 @@ build_nir_texel_fetch(struct nir_builder *b, 
>>> struct radv_device *device,
>>>           chans[2] = &layer->dest.ssa;
>>>           tex_pos_3d = nir_vec(b, chans, 3);
>>>       }
>>> +    if (is_multisampled) {
>>> +        sample_idx = nir_intrinsic_instr_create(b->shader, 
>>> nir_intrinsic_load_push_constant);
>>> +        nir_intrinsic_set_base(sample_idx, 20);
>>> +        nir_intrinsic_set_range(sample_idx, 4);
>>> +        sample_idx->src[0] = nir_src_for_ssa(nir_imm_int(b, 0));
>>> +        sample_idx->num_components = 1;
>>> +        nir_ssa_dest_init(&sample_idx->instr, &sample_idx->dest, 1, 
>>> 32, "sample_idx");
>>> +        nir_builder_instr_insert(b, &sample_idx->instr);
>>> +    }
>>>       nir_tex_instr *tex = nir_tex_instr_create(b->shader, 2);
>>>       tex->sampler_dim = dim;
>>> -    tex->op = nir_texop_txf;
>>> +    tex->op = is_multisampled ? nir_texop_txf_ms : nir_texop_txf;
>>>       tex->src[0].src_type = nir_tex_src_coord;
>>>       tex->src[0].src = nir_src_for_ssa(is_3d ? tex_pos_3d : tex_pos);
>>> -    tex->src[1].src_type = nir_tex_src_lod;
>>> -    tex->src[1].src = nir_src_for_ssa(nir_imm_int(b, 0));
>>> +    tex->src[1].src_type = is_multisampled ? nir_tex_src_ms_index : 
>>> nir_tex_src_lod;
>>> +    tex->src[1].src = nir_src_for_ssa(is_multisampled ? 
>>> &sample_idx->dest.ssa : nir_imm_int(b, 0));
>>>       tex->dest_type = nir_type_uint;
>>>       tex->is_array = false;
>>>       tex->coord_components = is_3d ? 3 : 2;
>>> @@ -473,7 +507,7 @@ build_nir_texel_fetch(struct nir_builder *b, 
>>> struct radv_device *device,
>>>     static nir_ssa_def *
>>>   build_nir_buffer_fetch(struct nir_builder *b, struct radv_device 
>>> *device,
>>> -               nir_ssa_def *tex_pos, bool is_3d)
>>> +               nir_ssa_def *tex_pos, bool is_3d, bool is_multisampled)
>>>   {
>>>       const struct glsl_type *sampler_type =
>>>           glsl_sampler_type(GLSL_SAMPLER_DIM_BUF, false, false, 
>>> GLSL_TYPE_UINT);
>>> @@ -519,9 +553,31 @@ static const 
>>> VkPipelineVertexInputStateCreateInfo normal_vi_create_info = {
>>>       .vertexAttributeDescriptionCount = 0,
>>>   };
>>>   +static void
>>> +build_nir_store_sample_mask(struct nir_builder *b)
>>> +{
>>> +    nir_intrinsic_instr *sample_mask = 
>>> nir_intrinsic_instr_create(b->shader, nir_intrinsic_load_push_constant);
>>> +    nir_intrinsic_set_base(sample_mask, 24);
>>> +    nir_intrinsic_set_range(sample_mask, 4);
>>> +    sample_mask->src[0] = nir_src_for_ssa(nir_imm_int(b, 0));
>>> +    sample_mask->num_components = 1;
>>> +    nir_ssa_dest_init(&sample_mask->instr, &sample_mask->dest, 1, 
>>> 32, "sample_mask");
>>> +    nir_builder_instr_insert(b, &sample_mask->instr);
>>> +
>>> +    const struct glsl_type *sample_mask_out_type = glsl_uint_type();
>>> +
>>> +    nir_variable *sample_mask_out =
>>> +        nir_variable_create(b->shader, nir_var_shader_out,
>>> +                    sample_mask_out_type, "sample_mask_out");
>>> +    sample_mask_out->data.location = FRAG_RESULT_SAMPLE_MASK;
>>> +
>>> +    nir_store_var(b, sample_mask_out, &sample_mask->dest.ssa, 0x1);
>>> +}
>>> +
>>>   static nir_shader *
>>>   build_nir_copy_fragment_shader(struct radv_device *device,
>>> -                               texel_fetch_build_func txf_func, 
>>> const char* name, bool is_3d)
>>> +                               texel_fetch_build_func txf_func, 
>>> const char* name, bool is_3d,
>>> +                               bool is_multisampled)
>>>   {
>>>       const struct glsl_type *vec4 = glsl_vec4_type();
>>>       const struct glsl_type *vec2 = 
>>> glsl_vector_type(GLSL_TYPE_FLOAT, 2);
>>> @@ -538,11 +594,15 @@ build_nir_copy_fragment_shader(struct 
>>> radv_device *device,
>>>                                 vec4, "f_color");
>>>       color_out->data.location = FRAG_RESULT_DATA0;
>>>   +    if (is_multisampled) {
>>> +        build_nir_store_sample_mask(&b);
>>> +    }
>>> +
>>>       nir_ssa_def *pos_int = nir_f2i32(&b, nir_load_var(&b, 
>>> tex_pos_in));
>>>       unsigned swiz[4] = { 0, 1 };
>>>       nir_ssa_def *tex_pos = nir_swizzle(&b, pos_int, swiz, 2, false);
>>>   -    nir_ssa_def *color = txf_func(&b, device, tex_pos, is_3d);
>>> +    nir_ssa_def *color = txf_func(&b, device, tex_pos, is_3d, 
>>> is_multisampled);
>>>       nir_store_var(&b, color_out, color, 0xf);
>>>         return b.shader;
>>> @@ -550,7 +610,8 @@ build_nir_copy_fragment_shader(struct radv_device 
>>> *device,
>>>     static nir_shader *
>>>   build_nir_copy_fragment_shader_depth(struct radv_device *device,
>>> -                     texel_fetch_build_func txf_func, const char* 
>>> name, bool is_3d)
>>> +                     texel_fetch_build_func txf_func, const char* 
>>> name, bool is_3d,
>>> +                     bool is_multisampled)
>>>   {
>>>       const struct glsl_type *vec4 = glsl_vec4_type();
>>>       const struct glsl_type *vec2 = 
>>> glsl_vector_type(GLSL_TYPE_FLOAT, 2);
>>> @@ -567,11 +628,15 @@ build_nir_copy_fragment_shader_depth(struct 
>>> radv_device *device,
>>>                                 vec4, "f_color");
>>>       color_out->data.location = FRAG_RESULT_DEPTH;
>>>   +    if (is_multisampled) {
>>> +        build_nir_store_sample_mask(&b);
>>> +    }
>>> +
>>>       nir_ssa_def *pos_int = nir_f2i32(&b, nir_load_var(&b, 
>>> tex_pos_in));
>>>       unsigned swiz[4] = { 0, 1 };
>>>       nir_ssa_def *tex_pos = nir_swizzle(&b, pos_int, swiz, 2, false);
>>>   -    nir_ssa_def *color = txf_func(&b, device, tex_pos, is_3d);
>>> +    nir_ssa_def *color = txf_func(&b, device, tex_pos, is_3d, 
>>> is_multisampled);
>>>       nir_store_var(&b, color_out, color, 0x1);
>>>         return b.shader;
>>> @@ -579,7 +644,8 @@ build_nir_copy_fragment_shader_depth(struct 
>>> radv_device *device,
>>>     static nir_shader *
>>>   build_nir_copy_fragment_shader_stencil(struct radv_device *device,
>>> -                       texel_fetch_build_func txf_func, const char* 
>>> name, bool is_3d)
>>> +                       texel_fetch_build_func txf_func, const char* 
>>> name, bool is_3d,
>>> +                       bool is_multisampled)
>>>   {
>>>       const struct glsl_type *vec4 = glsl_vec4_type();
>>>       const struct glsl_type *vec2 = 
>>> glsl_vector_type(GLSL_TYPE_FLOAT, 2);
>>> @@ -596,11 +662,15 @@ build_nir_copy_fragment_shader_stencil(struct 
>>> radv_device *device,
>>>                                 vec4, "f_color");
>>>       color_out->data.location = FRAG_RESULT_STENCIL;
>>>   +    if (is_multisampled) {
>>> +        build_nir_store_sample_mask(&b);
>>> +    }
>>> +
>>>       nir_ssa_def *pos_int = nir_f2i32(&b, nir_load_var(&b, 
>>> tex_pos_in));
>>>       unsigned swiz[4] = { 0, 1 };
>>>       nir_ssa_def *tex_pos = nir_swizzle(&b, pos_int, swiz, 2, false);
>>>   -    nir_ssa_def *color = txf_func(&b, device, tex_pos, is_3d);
>>> +    nir_ssa_def *color = txf_func(&b, device, tex_pos, is_3d, 
>>> is_multisampled);
>>>       nir_store_var(&b, color_out, color, 0x1);
>>>         return b.shader;
>>> @@ -614,45 +684,48 @@ radv_device_finish_meta_blit2d_state(struct 
>>> radv_device *device)
>>>       for(unsigned j = 0; j < NUM_META_FS_KEYS; ++j) {
>>>           for (unsigned k = 0; k < RADV_META_DST_LAYOUT_COUNT; ++k) {
>>> radv_DestroyRenderPass(radv_device_to_handle(device),
>>> - state->blit2d.render_passes[j][k],
>>> -                                   &state->alloc);
>>> + state->blit2d_render_passes[j][k],
>>> +                           &state->alloc);
>>>           }
>>>       }
>>>         for (enum radv_blit_ds_layout j = 
>>> RADV_BLIT_DS_LAYOUT_TILE_ENABLE; j < RADV_BLIT_DS_LAYOUT_COUNT; j++) {
>>>           radv_DestroyRenderPass(radv_device_to_handle(device),
>>> -                       state->blit2d.depth_only_rp[j], &state->alloc);
>>> +                       state->blit2d_depth_only_rp[j], &state->alloc);
>>>           radv_DestroyRenderPass(radv_device_to_handle(device),
>>> -                       state->blit2d.stencil_only_rp[j], 
>>> &state->alloc);
>>> +                       state->blit2d_stencil_only_rp[j], 
>>> &state->alloc);
>>>       }
>>>   -    for (unsigned src = 0; src < BLIT2D_NUM_SRC_TYPES; src++) {
>>> - radv_DestroyPipelineLayout(radv_device_to_handle(device),
>>> -                       state->blit2d.p_layouts[src],
>>> -                       &state->alloc);
>>> - radv_DestroyDescriptorSetLayout(radv_device_to_handle(device),
>>> -                        state->blit2d.ds_layouts[src],
>>> -                        &state->alloc);
>>> +    for (unsigned log2_samples = 0; log2_samples < 1 + 
>>> MAX_SAMPLES_LOG2; ++log2_samples) {
>>> +        for (unsigned src = 0; src < BLIT2D_NUM_SRC_TYPES; src++) {
>>> + radv_DestroyPipelineLayout(radv_device_to_handle(device),
>>> + state->blit2d[log2_samples].p_layouts[src],
>>> +                           &state->alloc);
>>> + radv_DestroyDescriptorSetLayout(radv_device_to_handle(device),
>>> + state->blit2d[log2_samples].ds_layouts[src],
>>> +                            &state->alloc);
>>> +
>>> +            for (unsigned j = 0; j < NUM_META_FS_KEYS; ++j) {
>>> + radv_DestroyPipeline(radv_device_to_handle(device),
>>> + state->blit2d[log2_samples].pipelines[src][j],
>>> +                             &state->alloc);
>>> +            }
>>>   -        for (unsigned j = 0; j < NUM_META_FS_KEYS; ++j) {
>>> radv_DestroyPipeline(radv_device_to_handle(device),
>>> -                         state->blit2d.pipelines[src][j],
>>> + state->blit2d[log2_samples].depth_only_pipeline[src],
>>> +                         &state->alloc);
>>> +            radv_DestroyPipeline(radv_device_to_handle(device),
>>> + state->blit2d[log2_samples].stencil_only_pipeline[src],
>>>                            &state->alloc);
>>>           }
>>> -
>>> -        radv_DestroyPipeline(radv_device_to_handle(device),
>>> -                     state->blit2d.depth_only_pipeline[src],
>>> -                     &state->alloc);
>>> -        radv_DestroyPipeline(radv_device_to_handle(device),
>>> - state->blit2d.stencil_only_pipeline[src],
>>> -                     &state->alloc);
>>>       }
>>>   }
>>>     static VkResult
>>>   blit2d_init_color_pipeline(struct radv_device *device,
>>>                  enum blit2d_src_type src_type,
>>> -               VkFormat format)
>>> +               VkFormat format,
>>> +               uint32_t log2_samples)
>>>   {
>>>       VkResult result;
>>>       unsigned fs_key = radv_format_meta_fs_key(format);
>>> @@ -681,7 +754,7 @@ blit2d_init_color_pipeline(struct radv_device 
>>> *device,
>>>       struct radv_shader_module fs = { .nir = NULL };
>>>     -    fs.nir = build_nir_copy_fragment_shader(device, src_func, 
>>> name, src_type == BLIT2D_SRC_TYPE_IMAGE_3D);
>>> +    fs.nir = build_nir_copy_fragment_shader(device, src_func, name, 
>>> src_type == BLIT2D_SRC_TYPE_IMAGE_3D, log2_samples > 0);
>>>       vi_create_info = &normal_vi_create_info;
>>>         struct radv_shader_module vs = {
>>> @@ -705,7 +778,7 @@ blit2d_init_color_pipeline(struct radv_device 
>>> *device,
>>>       };
>>>         for (unsigned dst_layout = 0; dst_layout < 
>>> RADV_META_DST_LAYOUT_COUNT; ++dst_layout) {
>>> -        if 
>>> (!device->meta_state.blit2d.render_passes[fs_key][dst_layout]) {
>>> +        if 
>>> (!device->meta_state.blit2d_render_passes[fs_key][dst_layout]) {
>>>               VkImageLayout layout = 
>>> radv_meta_dst_layout_to_layout(dst_layout);
>>>                 result = 
>>> radv_CreateRenderPass(radv_device_to_handle(device),
>>> @@ -737,7 +810,7 @@ blit2d_init_color_pipeline(struct radv_device 
>>> *device,
>>>                           .pPreserveAttachments = (uint32_t[]) { 0 },
>>>                           },
>>>                           .dependencyCount = 0,
>>> -                    }, &device->meta_state.alloc, 
>>> &device->meta_state.blit2d.render_passes[fs_key][dst_layout]);
>>> +                    }, &device->meta_state.alloc, 
>>> &device->meta_state.blit2d_render_passes[fs_key][dst_layout]);
>>>           }
>>>       }
>>>   @@ -765,7 +838,7 @@ blit2d_init_color_pipeline(struct radv_device 
>>> *device,
>>>           },
>>>           .pMultisampleState = &(VkPipelineMultisampleStateCreateInfo) {
>>>               .sType = 
>>> VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
>>> -            .rasterizationSamples = 1,
>>> +            .rasterizationSamples = 1 << log2_samples,
>>>               .sampleShadingEnable = false,
>>>               .pSampleMask = (VkSampleMask[]) { UINT32_MAX },
>>>           },
>>> @@ -796,8 +869,8 @@ blit2d_init_color_pipeline(struct radv_device 
>>> *device,
>>>               },
>>>           },
>>>           .flags = 0,
>>> -        .layout = device->meta_state.blit2d.p_layouts[src_type],
>>> -        .renderPass = 
>>> device->meta_state.blit2d.render_passes[fs_key][0],
>>> +        .layout = 
>>> device->meta_state.blit2d[log2_samples].p_layouts[src_type],
>>> +        .renderPass = 
>>> device->meta_state.blit2d_render_passes[fs_key][0],
>>>           .subpass = 0,
>>>       };
>>>   @@ -809,7 +882,7 @@ blit2d_init_color_pipeline(struct radv_device 
>>> *device,
>>> radv_pipeline_cache_to_handle(&device->meta_state.cache),
>>>                              &vk_pipeline_info, &radv_pipeline_info,
>>>                              &device->meta_state.alloc,
>>> - &device->meta_state.blit2d.pipelines[src_type][fs_key]);
>>> + &device->meta_state.blit2d[log2_samples].pipelines[src_type][fs_key]);
>>>           ralloc_free(vs.nir);
>>> @@ -820,7 +893,8 @@ blit2d_init_color_pipeline(struct radv_device 
>>> *device,
>>>     static VkResult
>>>   blit2d_init_depth_only_pipeline(struct radv_device *device,
>>> -                enum blit2d_src_type src_type)
>>> +                enum blit2d_src_type src_type,
>>> +                uint32_t log2_samples)
>>>   {
>>>       VkResult result;
>>>       const char *name;
>>> @@ -847,7 +921,7 @@ blit2d_init_depth_only_pipeline(struct 
>>> radv_device *device,
>>>       const VkPipelineVertexInputStateCreateInfo *vi_create_info;
>>>       struct radv_shader_module fs = { .nir = NULL };
>>>   -    fs.nir = build_nir_copy_fragment_shader_depth(device, 
>>> src_func, name, src_type == BLIT2D_SRC_TYPE_IMAGE_3D);
>>> +    fs.nir = build_nir_copy_fragment_shader_depth(device, src_func, 
>>> name, src_type == BLIT2D_SRC_TYPE_IMAGE_3D, log2_samples > 0);
>>>       vi_create_info = &normal_vi_create_info;
>>>         struct radv_shader_module vs = {
>>> @@ -871,7 +945,7 @@ blit2d_init_depth_only_pipeline(struct 
>>> radv_device *device,
>>>       };
>>>         for (enum radv_blit_ds_layout ds_layout = 
>>> RADV_BLIT_DS_LAYOUT_TILE_ENABLE; ds_layout < 
>>> RADV_BLIT_DS_LAYOUT_COUNT; ds_layout++) {
>>> -        if (!device->meta_state.blit2d.depth_only_rp[ds_layout]) {
>>> +        if (!device->meta_state.blit2d_depth_only_rp[ds_layout]) {
>>>               VkImageLayout layout = 
>>> radv_meta_blit_ds_to_layout(ds_layout);
>>>               result = 
>>> radv_CreateRenderPass(radv_device_to_handle(device),
>>>                                  &(VkRenderPassCreateInfo) {
>>> @@ -899,7 +973,7 @@ blit2d_init_depth_only_pipeline(struct 
>>> radv_device *device,
>>>                                          .pPreserveAttachments = 
>>> (uint32_t[]) { 0 },
>>>                                      },
>>>                                      .dependencyCount = 0,
>>> -                            }, &device->meta_state.alloc, 
>>> &device->meta_state.blit2d.depth_only_rp[ds_layout]);
>>> +                            }, &device->meta_state.alloc, 
>>> &device->meta_state.blit2d_depth_only_rp[ds_layout]);
>>>           }
>>>       }
>>>   @@ -927,7 +1001,7 @@ blit2d_init_depth_only_pipeline(struct 
>>> radv_device *device,
>>>           },
>>>           .pMultisampleState = &(VkPipelineMultisampleStateCreateInfo) {
>>>               .sType = 
>>> VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
>>> -            .rasterizationSamples = 1,
>>> +            .rasterizationSamples = 1 << log2_samples,
>>>               .sampleShadingEnable = false,
>>>               .pSampleMask = (VkSampleMask[]) { UINT32_MAX },
>>>           },
>>> @@ -958,8 +1032,8 @@ blit2d_init_depth_only_pipeline(struct 
>>> radv_device *device,
>>>               },
>>>           },
>>>           .flags = 0,
>>> -        .layout = device->meta_state.blit2d.p_layouts[src_type],
>>> -        .renderPass = device->meta_state.blit2d.depth_only_rp[0],
>>> +        .layout = 
>>> device->meta_state.blit2d[log2_samples].p_layouts[src_type],
>>> +        .renderPass = device->meta_state.blit2d_depth_only_rp[0],
>>>           .subpass = 0,
>>>       };
>>>   @@ -971,7 +1045,7 @@ blit2d_init_depth_only_pipeline(struct 
>>> radv_device *device,
>>> radv_pipeline_cache_to_handle(&device->meta_state.cache),
>>>                              &vk_pipeline_info, &radv_pipeline_info,
>>>                              &device->meta_state.alloc,
>>> - &device->meta_state.blit2d.depth_only_pipeline[src_type]);
>>> + 
>>> &device->meta_state.blit2d[log2_samples].depth_only_pipeline[src_type]);
>>>           ralloc_free(vs.nir);
>>> @@ -982,7 +1056,8 @@ blit2d_init_depth_only_pipeline(struct 
>>> radv_device *device,
>>>     static VkResult
>>>   blit2d_init_stencil_only_pipeline(struct radv_device *device,
>>> -                  enum blit2d_src_type src_type)
>>> +                  enum blit2d_src_type src_type,
>>> +                  uint32_t log2_samples)
>>>   {
>>>       VkResult result;
>>>       const char *name;
>>> @@ -1009,7 +1084,7 @@ blit2d_init_stencil_only_pipeline(struct 
>>> radv_device *device,
>>>       const VkPipelineVertexInputStateCreateInfo *vi_create_info;
>>>       struct radv_shader_module fs = { .nir = NULL };
>>>   -    fs.nir = build_nir_copy_fragment_shader_stencil(device, 
>>> src_func, name, src_type == BLIT2D_SRC_TYPE_IMAGE_3D);
>>> +    fs.nir = build_nir_copy_fragment_shader_stencil(device, 
>>> src_func, name, src_type == BLIT2D_SRC_TYPE_IMAGE_3D, log2_samples > 0);
>>>       vi_create_info = &normal_vi_create_info;
>>>         struct radv_shader_module vs = {
>>> @@ -1033,7 +1108,7 @@ blit2d_init_stencil_only_pipeline(struct 
>>> radv_device *device,
>>>       };
>>>         for (enum radv_blit_ds_layout ds_layout = 
>>> RADV_BLIT_DS_LAYOUT_TILE_ENABLE; ds_layout < 
>>> RADV_BLIT_DS_LAYOUT_COUNT; ds_layout++) {
>>> -        if (!device->meta_state.blit2d.stencil_only_rp[ds_layout]) {
>>> +        if (!device->meta_state.blit2d_stencil_only_rp[ds_layout]) {
>>>               VkImageLayout layout = 
>>> radv_meta_blit_ds_to_layout(ds_layout);
>>>               result = 
>>> radv_CreateRenderPass(radv_device_to_handle(device),
>>>                                  &(VkRenderPassCreateInfo) {
>>> @@ -1061,7 +1136,7 @@ blit2d_init_stencil_only_pipeline(struct 
>>> radv_device *device,
>>>                                          .pPreserveAttachments = 
>>> (uint32_t[]) { 0 },
>>>                                      },
>>>                                      .dependencyCount = 0,
>>> -                               }, &device->meta_state.alloc, 
>>> &device->meta_state.blit2d.stencil_only_rp[ds_layout]);
>>> +                               }, &device->meta_state.alloc, 
>>> &device->meta_state.blit2d_stencil_only_rp[ds_layout]);
>>>           }
>>>       }
>>>   @@ -1089,7 +1164,7 @@ blit2d_init_stencil_only_pipeline(struct 
>>> radv_device *device,
>>>           },
>>>           .pMultisampleState = &(VkPipelineMultisampleStateCreateInfo) {
>>>               .sType = 
>>> VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
>>> -            .rasterizationSamples = 1,
>>> +            .rasterizationSamples = 1 << log2_samples,
>>>               .sampleShadingEnable = false,
>>>               .pSampleMask = (VkSampleMask[]) { UINT32_MAX },
>>>           },
>>> @@ -1136,8 +1211,8 @@ blit2d_init_stencil_only_pipeline(struct 
>>> radv_device *device,
>>>               },
>>>           },
>>>           .flags = 0,
>>> -        .layout = device->meta_state.blit2d.p_layouts[src_type],
>>> -        .renderPass = device->meta_state.blit2d.stencil_only_rp[0],
>>> +        .layout = 
>>> device->meta_state.blit2d[log2_samples].p_layouts[src_type],
>>> +        .renderPass = device->meta_state.blit2d_stencil_only_rp[0],
>>>           .subpass = 0,
>>>       };
>>>   @@ -1149,7 +1224,7 @@ blit2d_init_stencil_only_pipeline(struct 
>>> radv_device *device,
>>> radv_pipeline_cache_to_handle(&device->meta_state.cache),
>>>                              &vk_pipeline_info, &radv_pipeline_info,
>>>                              &device->meta_state.alloc,
>>> - &device->meta_state.blit2d.stencil_only_pipeline[src_type]);
>>> + 
>>> &device->meta_state.blit2d[log2_samples].stencil_only_pipeline[src_type]); 
>>>
>>>           ralloc_free(vs.nir);
>>> @@ -1175,15 +1250,16 @@ static VkFormat pipeline_formats[] = {
>>>     static VkResult
>>>   meta_blit2d_create_pipe_layout(struct radv_device *device,
>>> -                   int idx)
>>> +                   int idx,
>>> +                   uint32_t log2_samples)
>>>   {
>>>       VkResult result;
>>>       VkDescriptorType desc_type = (idx == BLIT2D_SRC_TYPE_BUFFER) ? 
>>> VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER : 
>>> VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
>>>       const VkPushConstantRange push_constant_ranges[] = {
>>>           {VK_SHADER_STAGE_VERTEX_BIT, 0, 16},
>>> -        {VK_SHADER_STAGE_FRAGMENT_BIT, 16, 4},
>>> +        {VK_SHADER_STAGE_FRAGMENT_BIT, 16, 12},
>>>       };
>>> -    int num_push_constant_range = (idx != BLIT2D_SRC_TYPE_IMAGE) ? 2 
>>> : 1;
>>> +    int num_push_constant_range = (idx != BLIT2D_SRC_TYPE_IMAGE || 
>>> log2_samples > 0) ? 2 : 1;
>>>         result = 
>>> radv_CreateDescriptorSetLayout(radv_device_to_handle(device),
>>>                           &(VkDescriptorSetLayoutCreateInfo) {
>>> @@ -1199,7 +1275,7 @@ meta_blit2d_create_pipe_layout(struct 
>>> radv_device *device,
>>>                                   .pImmutableSamplers = NULL
>>>                               },
>>>                               }
>>> -                        }, &device->meta_state.alloc, 
>>> &device->meta_state.blit2d.ds_layouts[idx]);
>>> +                        }, &device->meta_state.alloc, 
>>> &device->meta_state.blit2d[log2_samples].ds_layouts[idx]);
>>>       if (result != VK_SUCCESS)
>>>           goto fail;
>>>   @@ -1207,11 +1283,11 @@ meta_blit2d_create_pipe_layout(struct 
>>> radv_device *device,
>>>                          &(VkPipelineLayoutCreateInfo) {
>>>                              .sType = 
>>> VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
>>>                                  .setLayoutCount = 1,
>>> -                               .pSetLayouts = 
>>> &device->meta_state.blit2d.ds_layouts[idx],
>>> +                               .pSetLayouts = 
>>> &device->meta_state.blit2d[log2_samples].ds_layouts[idx],
>>>                                  .pushConstantRangeCount = 
>>> num_push_constant_range,
>>>                                  .pPushConstantRanges = 
>>> push_constant_ranges,
>>>                                  },
>>> -                       &device->meta_state.alloc, 
>>> &device->meta_state.blit2d.p_layouts[idx]);
>>> +                       &device->meta_state.alloc, 
>>> &device->meta_state.blit2d[log2_samples].p_layouts[idx]);
>>>       if (result != VK_SUCCESS)
>>>           goto fail;
>>>       return VK_SUCCESS;
>>> @@ -1225,27 +1301,33 @@ radv_device_init_meta_blit2d_state(struct 
>>> radv_device *device)
>>>       VkResult result;
>>>       bool create_3d = device->physical_device->rad_info.chip_class 
>>> >= GFX9;
>>>   -    for (unsigned src = 0; src < BLIT2D_NUM_SRC_TYPES; src++) {
>>> -        if (src == BLIT2D_SRC_TYPE_IMAGE_3D && !create_3d)
>>> -            continue;
>>> +    for (unsigned log2_samples = 0; log2_samples < 1 + 
>>> MAX_SAMPLES_LOG2; log2_samples++) {
>>> +        for (unsigned src = 0; src < BLIT2D_NUM_SRC_TYPES; src++) {
>>> +            if (src == BLIT2D_SRC_TYPE_IMAGE_3D && !create_3d)
>>> +                continue;
>>>   -        result = meta_blit2d_create_pipe_layout(device, src);
>>> -        if (result != VK_SUCCESS)
>>> -            goto fail;
>>> +            /* Don't need to handle copies between buffers and 
>>> multisample images. */
>>> +            if (src == BLIT2D_SRC_TYPE_BUFFER && log2_samples > 0)
>>> +                continue;
>>>   -        for (unsigned j = 0; j < ARRAY_SIZE(pipeline_formats); ++j) {
>>> -            result = blit2d_init_color_pipeline(device, src, 
>>> pipeline_formats[j]);
>>> +            result = meta_blit2d_create_pipe_layout(device, src, 
>>> log2_samples);
>>>               if (result != VK_SUCCESS)
>>>                   goto fail;
>>> -        }
>>>   -        result = blit2d_init_depth_only_pipeline(device, src);
>>> -        if (result != VK_SUCCESS)
>>> -            goto fail;
>>> +            for (unsigned j = 0; j < ARRAY_SIZE(pipeline_formats); 
>>> ++j) {
>>> +                result = blit2d_init_color_pipeline(device, src, 
>>> pipeline_formats[j], log2_samples);
>>> +                if (result != VK_SUCCESS)
>>> +                    goto fail;
>>> +            }
>>> +
>>> +            result = blit2d_init_depth_only_pipeline(device, src, 
>>> log2_samples);
>>> +            if (result != VK_SUCCESS)
>>> +                goto fail;
>>>   -        result = blit2d_init_stencil_only_pipeline(device, src);
>>> -        if (result != VK_SUCCESS)
>>> -            goto fail;
>>> +            result = blit2d_init_stencil_only_pipeline(device, src, 
>>> log2_samples);
>>> +            if (result != VK_SUCCESS)
>>> +                goto fail;
>>> +        }
>>>       }
>>>         return VK_SUCCESS;
>>> diff --git a/src/amd/vulkan/radv_private.h 
>>> b/src/amd/vulkan/radv_private.h
>>> index 883342ede88..5d67271961b 100644
>>> --- a/src/amd/vulkan/radv_private.h
>>> +++ b/src/amd/vulkan/radv_private.h
>>> @@ -465,18 +465,18 @@ struct radv_meta_state {
>>>       } blit;
>>>         struct {
>>> -        VkRenderPass 
>>> render_passes[NUM_META_FS_KEYS][RADV_META_DST_LAYOUT_COUNT];
>>> +        VkPipelineLayout p_layouts[5];
>>> +        VkDescriptorSetLayout ds_layouts[5];
>>> +        VkPipeline pipelines[5][NUM_META_FS_KEYS];
>>>   -        VkPipelineLayout p_layouts[3];
>>> -        VkDescriptorSetLayout ds_layouts[3];
>>> -        VkPipeline pipelines[3][NUM_META_FS_KEYS];
>>> +        VkPipeline depth_only_pipeline[5];
>>>   -        VkRenderPass depth_only_rp[RADV_BLIT_DS_LAYOUT_COUNT];
>>> -        VkPipeline depth_only_pipeline[3];
>>> +        VkPipeline stencil_only_pipeline[5];
>>> +    } blit2d[1 + MAX_SAMPLES_LOG2];
>>>   -        VkRenderPass stencil_only_rp[RADV_BLIT_DS_LAYOUT_COUNT];
>>> -        VkPipeline stencil_only_pipeline[3];
>>> -    } blit2d;
>>> +    VkRenderPass 
>>> blit2d_render_passes[NUM_META_FS_KEYS][RADV_META_DST_LAYOUT_COUNT];
>>> +    VkRenderPass blit2d_depth_only_rp[RADV_BLIT_DS_LAYOUT_COUNT];
>>> +    VkRenderPass blit2d_stencil_only_rp[RADV_BLIT_DS_LAYOUT_COUNT];
>>>         struct {
>>>           VkPipelineLayout img_p_layout;
>>>
>
On 04/27/2018 02:30 PM, Matthew Nicholls wrote:
> I've verified the V2 of my patch does still fix the original issue I was 
> seeing.

You checked on Polaris, right? Vega still has an issue, working on it. 
Won't be ready for rc2.

> 
> Thanks a bunch.
> 
> Matthew.
> 
> 
> On 27/04/18 12:26, Samuel Pitoiset wrote:
>> Matthew, can you double-check if v2 still fixes the issue for you? 
>> Thanks!
>>
>> On 04/27/2018 01:23 PM, Samuel Pitoiset wrote:
>>> From: Matthew Nicholls <mnicholls@feralinteractive.com>
>>>
>>> Previously before fb077b0728, the LOD parameter was being used in 
>>> place of the
>>> sample index, which would only copy the first sample to all samples 
>>> in the
>>> destination image. After that multisample image copies wouldn't copy 
>>> anything
>>> from my observations.
>>>
>>> This fixes some copy_and_blit CTS tests.
>>>
>>> v2: - use GLSL_SAMPLER_DIM_MS instead of 2D (Samuel)
>>>      - updated commit description (Samuel)
>>>
>>> Fix this properly by copying each sample in a separate radv_CmdDraw 
>>> and using a
>>> pipeline with the correct rasterizationSamples for the destination 
>>> image.
>>>
>>> Cc: 18.0 18.1 <mesa-stable@lists.freedesktop.org>
>>> ---
>>>   src/amd/vulkan/radv_meta_blit2d.c | 282 +++++++++++++++++++-----------
>>>   src/amd/vulkan/radv_private.h     |  18 +-
>>>   2 files changed, 191 insertions(+), 109 deletions(-)
>>>
>>> diff --git a/src/amd/vulkan/radv_meta_blit2d.c 
>>> b/src/amd/vulkan/radv_meta_blit2d.c
>>> index e163056257e..3ad032f5989 100644
>>> --- a/src/amd/vulkan/radv_meta_blit2d.c
>>> +++ b/src/amd/vulkan/radv_meta_blit2d.c
>>> @@ -100,7 +100,8 @@ blit2d_bind_src(struct radv_cmd_buffer *cmd_buffer,
>>>                   struct radv_meta_blit2d_buffer *src_buf,
>>>                   struct blit2d_src_temps *tmp,
>>>                   enum blit2d_src_type src_type, VkFormat depth_format,
>>> -                VkImageAspectFlagBits aspects)
>>> +                VkImageAspectFlagBits aspects,
>>> +                uint32_t log2_samples)
>>>   {
>>>       struct radv_device *device = cmd_buffer->device;
>>>   @@ -108,7 +109,7 @@ blit2d_bind_src(struct radv_cmd_buffer 
>>> *cmd_buffer,
>>>           create_bview(cmd_buffer, src_buf, &tmp->bview, depth_format);
>>>             radv_meta_push_descriptor_set(cmd_buffer, 
>>> VK_PIPELINE_BIND_POINT_GRAPHICS,
>>> - device->meta_state.blit2d.p_layouts[src_type],
>>> + device->meta_state.blit2d[log2_samples].p_layouts[src_type],
>>>                             0, /* set */
>>>                             1, /* descriptorWriteCount */
>>>                             (VkWriteDescriptorSet[]) {
>>> @@ -123,7 +124,7 @@ blit2d_bind_src(struct radv_cmd_buffer *cmd_buffer,
>>>                             });
>>> radv_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer),
>>> - device->meta_state.blit2d.p_layouts[src_type],
>>> + device->meta_state.blit2d[log2_samples].p_layouts[src_type],
>>>                         VK_SHADER_STAGE_FRAGMENT_BIT, 16, 4,
>>>                         &src_buf->pitch);
>>>       } else {
>>> @@ -131,12 +132,12 @@ blit2d_bind_src(struct radv_cmd_buffer 
>>> *cmd_buffer,
>>>             if (src_type == BLIT2D_SRC_TYPE_IMAGE_3D)
>>> radv_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer),
>>> - device->meta_state.blit2d.p_layouts[src_type],
>>> + device->meta_state.blit2d[log2_samples].p_layouts[src_type],
>>>                             VK_SHADER_STAGE_FRAGMENT_BIT, 16, 4,
>>>                             &src_img->layer);
>>>             radv_meta_push_descriptor_set(cmd_buffer, 
>>> VK_PIPELINE_BIND_POINT_GRAPHICS,
>>> - device->meta_state.blit2d.p_layouts[src_type],
>>> + device->meta_state.blit2d[log2_samples].p_layouts[src_type],
>>>                             0, /* set */
>>>                             1, /* descriptorWriteCount */
>>>                             (VkWriteDescriptorSet[]) {
>>> @@ -190,10 +191,11 @@ blit2d_bind_dst(struct radv_cmd_buffer 
>>> *cmd_buffer,
>>>     static void
>>>   bind_pipeline(struct radv_cmd_buffer *cmd_buffer,
>>> -              enum blit2d_src_type src_type, unsigned fs_key)
>>> +              enum blit2d_src_type src_type, unsigned fs_key,
>>> +              uint32_t log2_samples)
>>>   {
>>>       VkPipeline pipeline =
>>> - cmd_buffer->device->meta_state.blit2d.pipelines[src_type][fs_key];
>>> + 
>>> cmd_buffer->device->meta_state.blit2d[log2_samples].pipelines[src_type][fs_key]; 
>>>
>>> radv_CmdBindPipeline(radv_cmd_buffer_to_handle(cmd_buffer),
>>>                    VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
>>> @@ -201,10 +203,11 @@ bind_pipeline(struct radv_cmd_buffer *cmd_buffer,
>>>     static void
>>>   bind_depth_pipeline(struct radv_cmd_buffer *cmd_buffer,
>>> -            enum blit2d_src_type src_type)
>>> +            enum blit2d_src_type src_type,
>>> +            uint32_t log2_samples)
>>>   {
>>>       VkPipeline pipeline =
>>> - cmd_buffer->device->meta_state.blit2d.depth_only_pipeline[src_type];
>>> + 
>>> cmd_buffer->device->meta_state.blit2d[log2_samples].depth_only_pipeline[src_type]; 
>>>
>>> radv_CmdBindPipeline(radv_cmd_buffer_to_handle(cmd_buffer),
>>>                    VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
>>> @@ -212,10 +215,11 @@ bind_depth_pipeline(struct radv_cmd_buffer 
>>> *cmd_buffer,
>>>     static void
>>>   bind_stencil_pipeline(struct radv_cmd_buffer *cmd_buffer,
>>> -              enum blit2d_src_type src_type)
>>> +              enum blit2d_src_type src_type,
>>> +              uint32_t log2_samples)
>>>   {
>>>       VkPipeline pipeline =
>>> - cmd_buffer->device->meta_state.blit2d.stencil_only_pipeline[src_type];
>>> + 
>>> cmd_buffer->device->meta_state.blit2d[log2_samples].stencil_only_pipeline[src_type]; 
>>>
>>> radv_CmdBindPipeline(radv_cmd_buffer_to_handle(cmd_buffer),
>>>                    VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
>>> @@ -227,7 +231,8 @@ radv_meta_blit2d_normal_dst(struct 
>>> radv_cmd_buffer *cmd_buffer,
>>>                   struct radv_meta_blit2d_buffer *src_buf,
>>>                   struct radv_meta_blit2d_surf *dst,
>>>                   unsigned num_rects,
>>> -                struct radv_meta_blit2d_rect *rects, enum 
>>> blit2d_src_type src_type)
>>> +                struct radv_meta_blit2d_rect *rects, enum 
>>> blit2d_src_type src_type,
>>> +                uint32_t log2_samples)
>>>   {
>>>       struct radv_device *device = cmd_buffer->device;
>>>   @@ -241,7 +246,7 @@ radv_meta_blit2d_normal_dst(struct 
>>> radv_cmd_buffer *cmd_buffer,
>>>               else if (aspect_mask == VK_IMAGE_ASPECT_DEPTH_BIT)
>>>                   depth_format = 
>>> vk_format_depth_only(dst->image->vk_format);
>>>               struct blit2d_src_temps src_temps;
>>> -            blit2d_bind_src(cmd_buffer, src_img, src_buf, 
>>> &src_temps, src_type, depth_format, aspect_mask);
>>> +            blit2d_bind_src(cmd_buffer, src_img, src_buf, 
>>> &src_temps, src_type, depth_format, aspect_mask, log2_samples);
>>>                 struct blit2d_dst_temps dst_temps;
>>>               blit2d_bind_dst(cmd_buffer, dst, rects[r].dst_x + 
>>> rects[r].width,
>>> @@ -255,7 +260,7 @@ radv_meta_blit2d_normal_dst(struct 
>>> radv_cmd_buffer *cmd_buffer,
>>>               };
>>> radv_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer),
>>> - device->meta_state.blit2d.p_layouts[src_type],
>>> + device->meta_state.blit2d[log2_samples].p_layouts[src_type],
>>>                       VK_SHADER_STAGE_VERTEX_BIT, 0, 16,
>>>                       vertex_push_constants);
>>>   @@ -266,7 +271,7 @@ radv_meta_blit2d_normal_dst(struct 
>>> radv_cmd_buffer *cmd_buffer,
>>> radv_CmdBeginRenderPass(radv_cmd_buffer_to_handle(cmd_buffer),
>>>                               &(VkRenderPassBeginInfo) {
>>>                                   .sType = 
>>> VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
>>> -                                    .renderPass = 
>>> device->meta_state.blit2d.render_passes[fs_key][dst_layout],
>>> +                                    .renderPass = 
>>> device->meta_state.blit2d_render_passes[fs_key][dst_layout],
>>>                                       .framebuffer = dst_temps.fb,
>>>                                       .renderArea = {
>>>                                       .offset = { rects[r].dst_x, 
>>> rects[r].dst_y, },
>>> @@ -277,13 +282,13 @@ radv_meta_blit2d_normal_dst(struct 
>>> radv_cmd_buffer *cmd_buffer,
>>>                                           }, 
>>> VK_SUBPASS_CONTENTS_INLINE);
>>>     -                bind_pipeline(cmd_buffer, src_type, fs_key);
>>> +                bind_pipeline(cmd_buffer, src_type, fs_key, 
>>> log2_samples);
>>>               } else if (aspect_mask == VK_IMAGE_ASPECT_DEPTH_BIT) {
>>>                   enum radv_blit_ds_layout ds_layout = 
>>> radv_meta_blit_ds_to_type(dst->current_layout);
>>> radv_CmdBeginRenderPass(radv_cmd_buffer_to_handle(cmd_buffer),
>>>                               &(VkRenderPassBeginInfo) {
>>>                                   .sType = 
>>> VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
>>> -                                    .renderPass = 
>>> device->meta_state.blit2d.depth_only_rp[ds_layout],
>>> +                                    .renderPass = 
>>> device->meta_state.blit2d_depth_only_rp[ds_layout],
>>>                                       .framebuffer = dst_temps.fb,
>>>                                       .renderArea = {
>>>                                       .offset = { rects[r].dst_x, 
>>> rects[r].dst_y, },
>>> @@ -294,14 +299,14 @@ radv_meta_blit2d_normal_dst(struct 
>>> radv_cmd_buffer *cmd_buffer,
>>>                                           }, 
>>> VK_SUBPASS_CONTENTS_INLINE);
>>>     -                bind_depth_pipeline(cmd_buffer, src_type);
>>> +                bind_depth_pipeline(cmd_buffer, src_type, 
>>> log2_samples);
>>>                 } else if (aspect_mask == VK_IMAGE_ASPECT_STENCIL_BIT) {
>>>                   enum radv_blit_ds_layout ds_layout = 
>>> radv_meta_blit_ds_to_type(dst->current_layout);
>>> radv_CmdBeginRenderPass(radv_cmd_buffer_to_handle(cmd_buffer),
>>>                               &(VkRenderPassBeginInfo) {
>>>                                   .sType = 
>>> VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
>>> -                                    .renderPass = 
>>> device->meta_state.blit2d.stencil_only_rp[ds_layout],
>>> +                                    .renderPass = 
>>> device->meta_state.blit2d_stencil_only_rp[ds_layout],
>>>                                       .framebuffer = dst_temps.fb,
>>>                                       .renderArea = {
>>>                                       .offset = { rects[r].dst_x, 
>>> rects[r].dst_y, },
>>> @@ -312,7 +317,7 @@ radv_meta_blit2d_normal_dst(struct 
>>> radv_cmd_buffer *cmd_buffer,
>>>                                           }, 
>>> VK_SUBPASS_CONTENTS_INLINE);
>>>     -                bind_stencil_pipeline(cmd_buffer, src_type);
>>> +                bind_stencil_pipeline(cmd_buffer, src_type, 
>>> log2_samples);
>>>               } else
>>>                   unreachable("Processing blit2d with multiple 
>>> aspects.");
>>>   @@ -332,7 +337,24 @@ radv_meta_blit2d_normal_dst(struct 
>>> radv_cmd_buffer *cmd_buffer,
>>>       - radv_CmdDraw(radv_cmd_buffer_to_handle(cmd_buffer), 3, 1, 0, 0);
>>> +            if (log2_samples > 0) {
>>> +                for (uint32_t sample = 0; sample < 
>>> src_img->image->info.samples; sample++) {
>>> +                    uint32_t sample_mask = 1 << sample;
>>> + radv_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer),
>>> + device->meta_state.blit2d[log2_samples].p_layouts[src_type],
>>> +                                  VK_SHADER_STAGE_FRAGMENT_BIT, 20, 4,
>>> +                                  &sample);
>>> +
>>> + radv_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer),
>>> + device->meta_state.blit2d[log2_samples].p_layouts[src_type],
>>> +                                  VK_SHADER_STAGE_FRAGMENT_BIT, 24, 4,
>>> +                                  &sample_mask);
>>> +
>>> + radv_CmdDraw(radv_cmd_buffer_to_handle(cmd_buffer), 3, 1, 0, 0);
>>> +                }
>>> +            }
>>> +            else
>>> + radv_CmdDraw(radv_cmd_buffer_to_handle(cmd_buffer), 3, 1, 0, 0);
>>> radv_CmdEndRenderPass(radv_cmd_buffer_to_handle(cmd_buffer));
>>>                 /* At the point where we emit the draw call, all data 
>>> from the
>>> @@ -358,7 +380,8 @@ radv_meta_blit2d(struct radv_cmd_buffer *cmd_buffer,
>>>       enum blit2d_src_type src_type = src_buf ? BLIT2D_SRC_TYPE_BUFFER :
>>>           use_3d ? BLIT2D_SRC_TYPE_IMAGE_3D : BLIT2D_SRC_TYPE_IMAGE;
>>>       radv_meta_blit2d_normal_dst(cmd_buffer, src_img, src_buf, dst,
>>> -                    num_rects, rects, src_type);
>>> +                    num_rects, rects, src_type,
>>> +                    src_img ? 
>>> util_logbase2(src_img->image->info.samples) : 0);
>>>   }
>>>     static nir_shader *
>>> @@ -421,13 +444,14 @@ build_nir_vertex_shader(void)
>>>     typedef nir_ssa_def* (*texel_fetch_build_func)(struct nir_builder *,
>>>                                                  struct radv_device *,
>>> -                                               nir_ssa_def *, bool);
>>> +                                               nir_ssa_def *, bool, 
>>> bool);
>>>     static nir_ssa_def *
>>>   build_nir_texel_fetch(struct nir_builder *b, struct radv_device 
>>> *device,
>>> -                      nir_ssa_def *tex_pos, bool is_3d)
>>> +                      nir_ssa_def *tex_pos, bool is_3d, bool 
>>> is_multisampled)
>>>   {
>>> -    enum glsl_sampler_dim dim = is_3d ? GLSL_SAMPLER_DIM_3D : 
>>> GLSL_SAMPLER_DIM_2D;
>>> +    enum glsl_sampler_dim dim =
>>> +        is_3d ? GLSL_SAMPLER_DIM_3D : is_multisampled ? 
>>> GLSL_SAMPLER_DIM_MS : GLSL_SAMPLER_DIM_2D;
>>>       const struct glsl_type *sampler_type =
>>>           glsl_sampler_type(dim, false, false, GLSL_TYPE_UINT);
>>>       nir_variable *sampler = nir_variable_create(b->shader, 
>>> nir_var_uniform,
>>> @@ -436,6 +460,7 @@ build_nir_texel_fetch(struct nir_builder *b, 
>>> struct radv_device *device,
>>>       sampler->data.binding = 0;
>>>         nir_ssa_def *tex_pos_3d = NULL;
>>> +    nir_intrinsic_instr *sample_idx = NULL;
>>>       if (is_3d) {
>>>           nir_intrinsic_instr *layer = 
>>> nir_intrinsic_instr_create(b->shader, nir_intrinsic_load_push_constant);
>>>           nir_intrinsic_set_base(layer, 16);
>>> @@ -451,13 +476,22 @@ build_nir_texel_fetch(struct nir_builder *b, 
>>> struct radv_device *device,
>>>           chans[2] = &layer->dest.ssa;
>>>           tex_pos_3d = nir_vec(b, chans, 3);
>>>       }
>>> +    if (is_multisampled) {
>>> +        sample_idx = nir_intrinsic_instr_create(b->shader, 
>>> nir_intrinsic_load_push_constant);
>>> +        nir_intrinsic_set_base(sample_idx, 20);
>>> +        nir_intrinsic_set_range(sample_idx, 4);
>>> +        sample_idx->src[0] = nir_src_for_ssa(nir_imm_int(b, 0));
>>> +        sample_idx->num_components = 1;
>>> +        nir_ssa_dest_init(&sample_idx->instr, &sample_idx->dest, 1, 
>>> 32, "sample_idx");
>>> +        nir_builder_instr_insert(b, &sample_idx->instr);
>>> +    }
>>>       nir_tex_instr *tex = nir_tex_instr_create(b->shader, 2);
>>>       tex->sampler_dim = dim;
>>> -    tex->op = nir_texop_txf;
>>> +    tex->op = is_multisampled ? nir_texop_txf_ms : nir_texop_txf;
>>>       tex->src[0].src_type = nir_tex_src_coord;
>>>       tex->src[0].src = nir_src_for_ssa(is_3d ? tex_pos_3d : tex_pos);
>>> -    tex->src[1].src_type = nir_tex_src_lod;
>>> -    tex->src[1].src = nir_src_for_ssa(nir_imm_int(b, 0));
>>> +    tex->src[1].src_type = is_multisampled ? nir_tex_src_ms_index : 
>>> nir_tex_src_lod;
>>> +    tex->src[1].src = nir_src_for_ssa(is_multisampled ? 
>>> &sample_idx->dest.ssa : nir_imm_int(b, 0));
>>>       tex->dest_type = nir_type_uint;
>>>       tex->is_array = false;
>>>       tex->coord_components = is_3d ? 3 : 2;
>>> @@ -473,7 +507,7 @@ build_nir_texel_fetch(struct nir_builder *b, 
>>> struct radv_device *device,
>>>     static nir_ssa_def *
>>>   build_nir_buffer_fetch(struct nir_builder *b, struct radv_device 
>>> *device,
>>> -               nir_ssa_def *tex_pos, bool is_3d)
>>> +               nir_ssa_def *tex_pos, bool is_3d, bool is_multisampled)
>>>   {
>>>       const struct glsl_type *sampler_type =
>>>           glsl_sampler_type(GLSL_SAMPLER_DIM_BUF, false, false, 
>>> GLSL_TYPE_UINT);
>>> @@ -519,9 +553,31 @@ static const 
>>> VkPipelineVertexInputStateCreateInfo normal_vi_create_info = {
>>>       .vertexAttributeDescriptionCount = 0,
>>>   };
>>>   +static void
>>> +build_nir_store_sample_mask(struct nir_builder *b)
>>> +{
>>> +    nir_intrinsic_instr *sample_mask = 
>>> nir_intrinsic_instr_create(b->shader, nir_intrinsic_load_push_constant);
>>> +    nir_intrinsic_set_base(sample_mask, 24);
>>> +    nir_intrinsic_set_range(sample_mask, 4);
>>> +    sample_mask->src[0] = nir_src_for_ssa(nir_imm_int(b, 0));
>>> +    sample_mask->num_components = 1;
>>> +    nir_ssa_dest_init(&sample_mask->instr, &sample_mask->dest, 1, 
>>> 32, "sample_mask");
>>> +    nir_builder_instr_insert(b, &sample_mask->instr);
>>> +
>>> +    const struct glsl_type *sample_mask_out_type = glsl_uint_type();
>>> +
>>> +    nir_variable *sample_mask_out =
>>> +        nir_variable_create(b->shader, nir_var_shader_out,
>>> +                    sample_mask_out_type, "sample_mask_out");
>>> +    sample_mask_out->data.location = FRAG_RESULT_SAMPLE_MASK;
>>> +
>>> +    nir_store_var(b, sample_mask_out, &sample_mask->dest.ssa, 0x1);
>>> +}
>>> +
>>>   static nir_shader *
>>>   build_nir_copy_fragment_shader(struct radv_device *device,
>>> -                               texel_fetch_build_func txf_func, 
>>> const char* name, bool is_3d)
>>> +                               texel_fetch_build_func txf_func, 
>>> const char* name, bool is_3d,
>>> +                               bool is_multisampled)
>>>   {
>>>       const struct glsl_type *vec4 = glsl_vec4_type();
>>>       const struct glsl_type *vec2 = 
>>> glsl_vector_type(GLSL_TYPE_FLOAT, 2);
>>> @@ -538,11 +594,15 @@ build_nir_copy_fragment_shader(struct 
>>> radv_device *device,
>>>                                 vec4, "f_color");
>>>       color_out->data.location = FRAG_RESULT_DATA0;
>>>   +    if (is_multisampled) {
>>> +        build_nir_store_sample_mask(&b);
>>> +    }
>>> +
>>>       nir_ssa_def *pos_int = nir_f2i32(&b, nir_load_var(&b, 
>>> tex_pos_in));
>>>       unsigned swiz[4] = { 0, 1 };
>>>       nir_ssa_def *tex_pos = nir_swizzle(&b, pos_int, swiz, 2, false);
>>>   -    nir_ssa_def *color = txf_func(&b, device, tex_pos, is_3d);
>>> +    nir_ssa_def *color = txf_func(&b, device, tex_pos, is_3d, 
>>> is_multisampled);
>>>       nir_store_var(&b, color_out, color, 0xf);
>>>         return b.shader;
>>> @@ -550,7 +610,8 @@ build_nir_copy_fragment_shader(struct radv_device 
>>> *device,
>>>     static nir_shader *
>>>   build_nir_copy_fragment_shader_depth(struct radv_device *device,
>>> -                     texel_fetch_build_func txf_func, const char* 
>>> name, bool is_3d)
>>> +                     texel_fetch_build_func txf_func, const char* 
>>> name, bool is_3d,
>>> +                     bool is_multisampled)
>>>   {
>>>       const struct glsl_type *vec4 = glsl_vec4_type();
>>>       const struct glsl_type *vec2 = 
>>> glsl_vector_type(GLSL_TYPE_FLOAT, 2);
>>> @@ -567,11 +628,15 @@ build_nir_copy_fragment_shader_depth(struct 
>>> radv_device *device,
>>>                                 vec4, "f_color");
>>>       color_out->data.location = FRAG_RESULT_DEPTH;
>>>   +    if (is_multisampled) {
>>> +        build_nir_store_sample_mask(&b);
>>> +    }
>>> +
>>>       nir_ssa_def *pos_int = nir_f2i32(&b, nir_load_var(&b, 
>>> tex_pos_in));
>>>       unsigned swiz[4] = { 0, 1 };
>>>       nir_ssa_def *tex_pos = nir_swizzle(&b, pos_int, swiz, 2, false);
>>>   -    nir_ssa_def *color = txf_func(&b, device, tex_pos, is_3d);
>>> +    nir_ssa_def *color = txf_func(&b, device, tex_pos, is_3d, 
>>> is_multisampled);
>>>       nir_store_var(&b, color_out, color, 0x1);
>>>         return b.shader;
>>> @@ -579,7 +644,8 @@ build_nir_copy_fragment_shader_depth(struct 
>>> radv_device *device,
>>>     static nir_shader *
>>>   build_nir_copy_fragment_shader_stencil(struct radv_device *device,
>>> -                       texel_fetch_build_func txf_func, const char* 
>>> name, bool is_3d)
>>> +                       texel_fetch_build_func txf_func, const char* 
>>> name, bool is_3d,
>>> +                       bool is_multisampled)
>>>   {
>>>       const struct glsl_type *vec4 = glsl_vec4_type();
>>>       const struct glsl_type *vec2 = 
>>> glsl_vector_type(GLSL_TYPE_FLOAT, 2);
>>> @@ -596,11 +662,15 @@ build_nir_copy_fragment_shader_stencil(struct 
>>> radv_device *device,
>>>                                 vec4, "f_color");
>>>       color_out->data.location = FRAG_RESULT_STENCIL;
>>>   +    if (is_multisampled) {
>>> +        build_nir_store_sample_mask(&b);
>>> +    }
>>> +
>>>       nir_ssa_def *pos_int = nir_f2i32(&b, nir_load_var(&b, 
>>> tex_pos_in));
>>>       unsigned swiz[4] = { 0, 1 };
>>>       nir_ssa_def *tex_pos = nir_swizzle(&b, pos_int, swiz, 2, false);
>>>   -    nir_ssa_def *color = txf_func(&b, device, tex_pos, is_3d);
>>> +    nir_ssa_def *color = txf_func(&b, device, tex_pos, is_3d, 
>>> is_multisampled);
>>>       nir_store_var(&b, color_out, color, 0x1);
>>>         return b.shader;
>>> @@ -614,45 +684,48 @@ radv_device_finish_meta_blit2d_state(struct 
>>> radv_device *device)
>>>       for(unsigned j = 0; j < NUM_META_FS_KEYS; ++j) {
>>>           for (unsigned k = 0; k < RADV_META_DST_LAYOUT_COUNT; ++k) {
>>> radv_DestroyRenderPass(radv_device_to_handle(device),
>>> - state->blit2d.render_passes[j][k],
>>> -                                   &state->alloc);
>>> + state->blit2d_render_passes[j][k],
>>> +                           &state->alloc);
>>>           }
>>>       }
>>>         for (enum radv_blit_ds_layout j = 
>>> RADV_BLIT_DS_LAYOUT_TILE_ENABLE; j < RADV_BLIT_DS_LAYOUT_COUNT; j++) {
>>>           radv_DestroyRenderPass(radv_device_to_handle(device),
>>> -                       state->blit2d.depth_only_rp[j], &state->alloc);
>>> +                       state->blit2d_depth_only_rp[j], &state->alloc);
>>>           radv_DestroyRenderPass(radv_device_to_handle(device),
>>> -                       state->blit2d.stencil_only_rp[j], 
>>> &state->alloc);
>>> +                       state->blit2d_stencil_only_rp[j], 
>>> &state->alloc);
>>>       }
>>>   -    for (unsigned src = 0; src < BLIT2D_NUM_SRC_TYPES; src++) {
>>> - radv_DestroyPipelineLayout(radv_device_to_handle(device),
>>> -                       state->blit2d.p_layouts[src],
>>> -                       &state->alloc);
>>> - radv_DestroyDescriptorSetLayout(radv_device_to_handle(device),
>>> -                        state->blit2d.ds_layouts[src],
>>> -                        &state->alloc);
>>> +    for (unsigned log2_samples = 0; log2_samples < 1 + 
>>> MAX_SAMPLES_LOG2; ++log2_samples) {
>>> +        for (unsigned src = 0; src < BLIT2D_NUM_SRC_TYPES; src++) {
>>> + radv_DestroyPipelineLayout(radv_device_to_handle(device),
>>> + state->blit2d[log2_samples].p_layouts[src],
>>> +                           &state->alloc);
>>> + radv_DestroyDescriptorSetLayout(radv_device_to_handle(device),
>>> + state->blit2d[log2_samples].ds_layouts[src],
>>> +                            &state->alloc);
>>> +
>>> +            for (unsigned j = 0; j < NUM_META_FS_KEYS; ++j) {
>>> + radv_DestroyPipeline(radv_device_to_handle(device),
>>> + state->blit2d[log2_samples].pipelines[src][j],
>>> +                             &state->alloc);
>>> +            }
>>>   -        for (unsigned j = 0; j < NUM_META_FS_KEYS; ++j) {
>>> radv_DestroyPipeline(radv_device_to_handle(device),
>>> -                         state->blit2d.pipelines[src][j],
>>> + state->blit2d[log2_samples].depth_only_pipeline[src],
>>> +                         &state->alloc);
>>> +            radv_DestroyPipeline(radv_device_to_handle(device),
>>> + state->blit2d[log2_samples].stencil_only_pipeline[src],
>>>                            &state->alloc);
>>>           }
>>> -
>>> -        radv_DestroyPipeline(radv_device_to_handle(device),
>>> -                     state->blit2d.depth_only_pipeline[src],
>>> -                     &state->alloc);
>>> -        radv_DestroyPipeline(radv_device_to_handle(device),
>>> - state->blit2d.stencil_only_pipeline[src],
>>> -                     &state->alloc);
>>>       }
>>>   }
>>>     static VkResult
>>>   blit2d_init_color_pipeline(struct radv_device *device,
>>>                  enum blit2d_src_type src_type,
>>> -               VkFormat format)
>>> +               VkFormat format,
>>> +               uint32_t log2_samples)
>>>   {
>>>       VkResult result;
>>>       unsigned fs_key = radv_format_meta_fs_key(format);
>>> @@ -681,7 +754,7 @@ blit2d_init_color_pipeline(struct radv_device 
>>> *device,
>>>       struct radv_shader_module fs = { .nir = NULL };
>>>     -    fs.nir = build_nir_copy_fragment_shader(device, src_func, 
>>> name, src_type == BLIT2D_SRC_TYPE_IMAGE_3D);
>>> +    fs.nir = build_nir_copy_fragment_shader(device, src_func, name, 
>>> src_type == BLIT2D_SRC_TYPE_IMAGE_3D, log2_samples > 0);
>>>       vi_create_info = &normal_vi_create_info;
>>>         struct radv_shader_module vs = {
>>> @@ -705,7 +778,7 @@ blit2d_init_color_pipeline(struct radv_device 
>>> *device,
>>>       };
>>>         for (unsigned dst_layout = 0; dst_layout < 
>>> RADV_META_DST_LAYOUT_COUNT; ++dst_layout) {
>>> -        if 
>>> (!device->meta_state.blit2d.render_passes[fs_key][dst_layout]) {
>>> +        if 
>>> (!device->meta_state.blit2d_render_passes[fs_key][dst_layout]) {
>>>               VkImageLayout layout = 
>>> radv_meta_dst_layout_to_layout(dst_layout);
>>>                 result = 
>>> radv_CreateRenderPass(radv_device_to_handle(device),
>>> @@ -737,7 +810,7 @@ blit2d_init_color_pipeline(struct radv_device 
>>> *device,
>>>                           .pPreserveAttachments = (uint32_t[]) { 0 },
>>>                           },
>>>                           .dependencyCount = 0,
>>> -                    }, &device->meta_state.alloc, 
>>> &device->meta_state.blit2d.render_passes[fs_key][dst_layout]);
>>> +                    }, &device->meta_state.alloc, 
>>> &device->meta_state.blit2d_render_passes[fs_key][dst_layout]);
>>>           }
>>>       }
>>>   @@ -765,7 +838,7 @@ blit2d_init_color_pipeline(struct radv_device 
>>> *device,
>>>           },
>>>           .pMultisampleState = &(VkPipelineMultisampleStateCreateInfo) {
>>>               .sType = 
>>> VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
>>> -            .rasterizationSamples = 1,
>>> +            .rasterizationSamples = 1 << log2_samples,
>>>               .sampleShadingEnable = false,
>>>               .pSampleMask = (VkSampleMask[]) { UINT32_MAX },
>>>           },
>>> @@ -796,8 +869,8 @@ blit2d_init_color_pipeline(struct radv_device 
>>> *device,
>>>               },
>>>           },
>>>           .flags = 0,
>>> -        .layout = device->meta_state.blit2d.p_layouts[src_type],
>>> -        .renderPass = 
>>> device->meta_state.blit2d.render_passes[fs_key][0],
>>> +        .layout = 
>>> device->meta_state.blit2d[log2_samples].p_layouts[src_type],
>>> +        .renderPass = 
>>> device->meta_state.blit2d_render_passes[fs_key][0],
>>>           .subpass = 0,
>>>       };
>>>   @@ -809,7 +882,7 @@ blit2d_init_color_pipeline(struct radv_device 
>>> *device,
>>> radv_pipeline_cache_to_handle(&device->meta_state.cache),
>>>                              &vk_pipeline_info, &radv_pipeline_info,
>>>                              &device->meta_state.alloc,
>>> - &device->meta_state.blit2d.pipelines[src_type][fs_key]);
>>> + &device->meta_state.blit2d[log2_samples].pipelines[src_type][fs_key]);
>>>           ralloc_free(vs.nir);
>>> @@ -820,7 +893,8 @@ blit2d_init_color_pipeline(struct radv_device 
>>> *device,
>>>     static VkResult
>>>   blit2d_init_depth_only_pipeline(struct radv_device *device,
>>> -                enum blit2d_src_type src_type)
>>> +                enum blit2d_src_type src_type,
>>> +                uint32_t log2_samples)
>>>   {
>>>       VkResult result;
>>>       const char *name;
>>> @@ -847,7 +921,7 @@ blit2d_init_depth_only_pipeline(struct 
>>> radv_device *device,
>>>       const VkPipelineVertexInputStateCreateInfo *vi_create_info;
>>>       struct radv_shader_module fs = { .nir = NULL };
>>>   -    fs.nir = build_nir_copy_fragment_shader_depth(device, 
>>> src_func, name, src_type == BLIT2D_SRC_TYPE_IMAGE_3D);
>>> +    fs.nir = build_nir_copy_fragment_shader_depth(device, src_func, 
>>> name, src_type == BLIT2D_SRC_TYPE_IMAGE_3D, log2_samples > 0);
>>>       vi_create_info = &normal_vi_create_info;
>>>         struct radv_shader_module vs = {
>>> @@ -871,7 +945,7 @@ blit2d_init_depth_only_pipeline(struct 
>>> radv_device *device,
>>>       };
>>>         for (enum radv_blit_ds_layout ds_layout = 
>>> RADV_BLIT_DS_LAYOUT_TILE_ENABLE; ds_layout < 
>>> RADV_BLIT_DS_LAYOUT_COUNT; ds_layout++) {
>>> -        if (!device->meta_state.blit2d.depth_only_rp[ds_layout]) {
>>> +        if (!device->meta_state.blit2d_depth_only_rp[ds_layout]) {
>>>               VkImageLayout layout = 
>>> radv_meta_blit_ds_to_layout(ds_layout);
>>>               result = 
>>> radv_CreateRenderPass(radv_device_to_handle(device),
>>>                                  &(VkRenderPassCreateInfo) {
>>> @@ -899,7 +973,7 @@ blit2d_init_depth_only_pipeline(struct 
>>> radv_device *device,
>>>                                          .pPreserveAttachments = 
>>> (uint32_t[]) { 0 },
>>>                                      },
>>>                                      .dependencyCount = 0,
>>> -                            }, &device->meta_state.alloc, 
>>> &device->meta_state.blit2d.depth_only_rp[ds_layout]);
>>> +                            }, &device->meta_state.alloc, 
>>> &device->meta_state.blit2d_depth_only_rp[ds_layout]);
>>>           }
>>>       }
>>>   @@ -927,7 +1001,7 @@ blit2d_init_depth_only_pipeline(struct 
>>> radv_device *device,
>>>           },
>>>           .pMultisampleState = &(VkPipelineMultisampleStateCreateInfo) {
>>>               .sType = 
>>> VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
>>> -            .rasterizationSamples = 1,
>>> +            .rasterizationSamples = 1 << log2_samples,
>>>               .sampleShadingEnable = false,
>>>               .pSampleMask = (VkSampleMask[]) { UINT32_MAX },
>>>           },
>>> @@ -958,8 +1032,8 @@ blit2d_init_depth_only_pipeline(struct 
>>> radv_device *device,
>>>               },
>>>           },
>>>           .flags = 0,
>>> -        .layout = device->meta_state.blit2d.p_layouts[src_type],
>>> -        .renderPass = device->meta_state.blit2d.depth_only_rp[0],
>>> +        .layout = 
>>> device->meta_state.blit2d[log2_samples].p_layouts[src_type],
>>> +        .renderPass = device->meta_state.blit2d_depth_only_rp[0],
>>>           .subpass = 0,
>>>       };
>>>   @@ -971,7 +1045,7 @@ blit2d_init_depth_only_pipeline(struct 
>>> radv_device *device,
>>> radv_pipeline_cache_to_handle(&device->meta_state.cache),
>>>                              &vk_pipeline_info, &radv_pipeline_info,
>>>                              &device->meta_state.alloc,
>>> - &device->meta_state.blit2d.depth_only_pipeline[src_type]);
>>> + 
>>> &device->meta_state.blit2d[log2_samples].depth_only_pipeline[src_type]);
>>>           ralloc_free(vs.nir);
>>> @@ -982,7 +1056,8 @@ blit2d_init_depth_only_pipeline(struct 
>>> radv_device *device,
>>>     static VkResult
>>>   blit2d_init_stencil_only_pipeline(struct radv_device *device,
>>> -                  enum blit2d_src_type src_type)
>>> +                  enum blit2d_src_type src_type,
>>> +                  uint32_t log2_samples)
>>>   {
>>>       VkResult result;
>>>       const char *name;
>>> @@ -1009,7 +1084,7 @@ blit2d_init_stencil_only_pipeline(struct 
>>> radv_device *device,
>>>       const VkPipelineVertexInputStateCreateInfo *vi_create_info;
>>>       struct radv_shader_module fs = { .nir = NULL };
>>>   -    fs.nir = build_nir_copy_fragment_shader_stencil(device, 
>>> src_func, name, src_type == BLIT2D_SRC_TYPE_IMAGE_3D);
>>> +    fs.nir = build_nir_copy_fragment_shader_stencil(device, 
>>> src_func, name, src_type == BLIT2D_SRC_TYPE_IMAGE_3D, log2_samples > 0);
>>>       vi_create_info = &normal_vi_create_info;
>>>         struct radv_shader_module vs = {
>>> @@ -1033,7 +1108,7 @@ blit2d_init_stencil_only_pipeline(struct 
>>> radv_device *device,
>>>       };
>>>         for (enum radv_blit_ds_layout ds_layout = 
>>> RADV_BLIT_DS_LAYOUT_TILE_ENABLE; ds_layout < 
>>> RADV_BLIT_DS_LAYOUT_COUNT; ds_layout++) {
>>> -        if (!device->meta_state.blit2d.stencil_only_rp[ds_layout]) {
>>> +        if (!device->meta_state.blit2d_stencil_only_rp[ds_layout]) {
>>>               VkImageLayout layout = 
>>> radv_meta_blit_ds_to_layout(ds_layout);
>>>               result = 
>>> radv_CreateRenderPass(radv_device_to_handle(device),
>>>                                  &(VkRenderPassCreateInfo) {
>>> @@ -1061,7 +1136,7 @@ blit2d_init_stencil_only_pipeline(struct 
>>> radv_device *device,
>>>                                          .pPreserveAttachments = 
>>> (uint32_t[]) { 0 },
>>>                                      },
>>>                                      .dependencyCount = 0,
>>> -                               }, &device->meta_state.alloc, 
>>> &device->meta_state.blit2d.stencil_only_rp[ds_layout]);
>>> +                               }, &device->meta_state.alloc, 
>>> &device->meta_state.blit2d_stencil_only_rp[ds_layout]);
>>>           }
>>>       }
>>>   @@ -1089,7 +1164,7 @@ blit2d_init_stencil_only_pipeline(struct 
>>> radv_device *device,
>>>           },
>>>           .pMultisampleState = &(VkPipelineMultisampleStateCreateInfo) {
>>>               .sType = 
>>> VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
>>> -            .rasterizationSamples = 1,
>>> +            .rasterizationSamples = 1 << log2_samples,
>>>               .sampleShadingEnable = false,
>>>               .pSampleMask = (VkSampleMask[]) { UINT32_MAX },
>>>           },
>>> @@ -1136,8 +1211,8 @@ blit2d_init_stencil_only_pipeline(struct 
>>> radv_device *device,
>>>               },
>>>           },
>>>           .flags = 0,
>>> -        .layout = device->meta_state.blit2d.p_layouts[src_type],
>>> -        .renderPass = device->meta_state.blit2d.stencil_only_rp[0],
>>> +        .layout = 
>>> device->meta_state.blit2d[log2_samples].p_layouts[src_type],
>>> +        .renderPass = device->meta_state.blit2d_stencil_only_rp[0],
>>>           .subpass = 0,
>>>       };
>>>   @@ -1149,7 +1224,7 @@ blit2d_init_stencil_only_pipeline(struct 
>>> radv_device *device,
>>> radv_pipeline_cache_to_handle(&device->meta_state.cache),
>>>                              &vk_pipeline_info, &radv_pipeline_info,
>>>                              &device->meta_state.alloc,
>>> - &device->meta_state.blit2d.stencil_only_pipeline[src_type]);
>>> + 
>>> &device->meta_state.blit2d[log2_samples].stencil_only_pipeline[src_type]); 
>>>
>>>           ralloc_free(vs.nir);
>>> @@ -1175,15 +1250,16 @@ static VkFormat pipeline_formats[] = {
>>>     static VkResult
>>>   meta_blit2d_create_pipe_layout(struct radv_device *device,
>>> -                   int idx)
>>> +                   int idx,
>>> +                   uint32_t log2_samples)
>>>   {
>>>       VkResult result;
>>>       VkDescriptorType desc_type = (idx == BLIT2D_SRC_TYPE_BUFFER) ? 
>>> VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER : 
>>> VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
>>>       const VkPushConstantRange push_constant_ranges[] = {
>>>           {VK_SHADER_STAGE_VERTEX_BIT, 0, 16},
>>> -        {VK_SHADER_STAGE_FRAGMENT_BIT, 16, 4},
>>> +        {VK_SHADER_STAGE_FRAGMENT_BIT, 16, 12},
>>>       };
>>> -    int num_push_constant_range = (idx != BLIT2D_SRC_TYPE_IMAGE) ? 2 
>>> : 1;
>>> +    int num_push_constant_range = (idx != BLIT2D_SRC_TYPE_IMAGE || 
>>> log2_samples > 0) ? 2 : 1;
>>>         result = 
>>> radv_CreateDescriptorSetLayout(radv_device_to_handle(device),
>>>                           &(VkDescriptorSetLayoutCreateInfo) {
>>> @@ -1199,7 +1275,7 @@ meta_blit2d_create_pipe_layout(struct 
>>> radv_device *device,
>>>                                   .pImmutableSamplers = NULL
>>>                               },
>>>                               }
>>> -                        }, &device->meta_state.alloc, 
>>> &device->meta_state.blit2d.ds_layouts[idx]);
>>> +                        }, &device->meta_state.alloc, 
>>> &device->meta_state.blit2d[log2_samples].ds_layouts[idx]);
>>>       if (result != VK_SUCCESS)
>>>           goto fail;
>>>   @@ -1207,11 +1283,11 @@ meta_blit2d_create_pipe_layout(struct 
>>> radv_device *device,
>>>                          &(VkPipelineLayoutCreateInfo) {
>>>                              .sType = 
>>> VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
>>>                                  .setLayoutCount = 1,
>>> -                               .pSetLayouts = 
>>> &device->meta_state.blit2d.ds_layouts[idx],
>>> +                               .pSetLayouts = 
>>> &device->meta_state.blit2d[log2_samples].ds_layouts[idx],
>>>                                  .pushConstantRangeCount = 
>>> num_push_constant_range,
>>>                                  .pPushConstantRanges = 
>>> push_constant_ranges,
>>>                                  },
>>> -                       &device->meta_state.alloc, 
>>> &device->meta_state.blit2d.p_layouts[idx]);
>>> +                       &device->meta_state.alloc, 
>>> &device->meta_state.blit2d[log2_samples].p_layouts[idx]);
>>>       if (result != VK_SUCCESS)
>>>           goto fail;
>>>       return VK_SUCCESS;
>>> @@ -1225,27 +1301,33 @@ radv_device_init_meta_blit2d_state(struct 
>>> radv_device *device)
>>>       VkResult result;
>>>       bool create_3d = device->physical_device->rad_info.chip_class 
>>> >= GFX9;
>>>   -    for (unsigned src = 0; src < BLIT2D_NUM_SRC_TYPES; src++) {
>>> -        if (src == BLIT2D_SRC_TYPE_IMAGE_3D && !create_3d)
>>> -            continue;
>>> +    for (unsigned log2_samples = 0; log2_samples < 1 + 
>>> MAX_SAMPLES_LOG2; log2_samples++) {
>>> +        for (unsigned src = 0; src < BLIT2D_NUM_SRC_TYPES; src++) {
>>> +            if (src == BLIT2D_SRC_TYPE_IMAGE_3D && !create_3d)
>>> +                continue;
>>>   -        result = meta_blit2d_create_pipe_layout(device, src);
>>> -        if (result != VK_SUCCESS)
>>> -            goto fail;
>>> +            /* Don't need to handle copies between buffers and 
>>> multisample images. */
>>> +            if (src == BLIT2D_SRC_TYPE_BUFFER && log2_samples > 0)
>>> +                continue;
>>>   -        for (unsigned j = 0; j < ARRAY_SIZE(pipeline_formats); ++j) {
>>> -            result = blit2d_init_color_pipeline(device, src, 
>>> pipeline_formats[j]);
>>> +            result = meta_blit2d_create_pipe_layout(device, src, 
>>> log2_samples);
>>>               if (result != VK_SUCCESS)
>>>                   goto fail;
>>> -        }
>>>   -        result = blit2d_init_depth_only_pipeline(device, src);
>>> -        if (result != VK_SUCCESS)
>>> -            goto fail;
>>> +            for (unsigned j = 0; j < ARRAY_SIZE(pipeline_formats); 
>>> ++j) {
>>> +                result = blit2d_init_color_pipeline(device, src, 
>>> pipeline_formats[j], log2_samples);
>>> +                if (result != VK_SUCCESS)
>>> +                    goto fail;
>>> +            }
>>> +
>>> +            result = blit2d_init_depth_only_pipeline(device, src, 
>>> log2_samples);
>>> +            if (result != VK_SUCCESS)
>>> +                goto fail;
>>>   -        result = blit2d_init_stencil_only_pipeline(device, src);
>>> -        if (result != VK_SUCCESS)
>>> -            goto fail;
>>> +            result = blit2d_init_stencil_only_pipeline(device, src, 
>>> log2_samples);
>>> +            if (result != VK_SUCCESS)
>>> +                goto fail;
>>> +        }
>>>       }
>>>         return VK_SUCCESS;
>>> diff --git a/src/amd/vulkan/radv_private.h 
>>> b/src/amd/vulkan/radv_private.h
>>> index 883342ede88..5d67271961b 100644
>>> --- a/src/amd/vulkan/radv_private.h
>>> +++ b/src/amd/vulkan/radv_private.h
>>> @@ -465,18 +465,18 @@ struct radv_meta_state {
>>>       } blit;
>>>         struct {
>>> -        VkRenderPass 
>>> render_passes[NUM_META_FS_KEYS][RADV_META_DST_LAYOUT_COUNT];
>>> +        VkPipelineLayout p_layouts[5];
>>> +        VkDescriptorSetLayout ds_layouts[5];
>>> +        VkPipeline pipelines[5][NUM_META_FS_KEYS];
>>>   -        VkPipelineLayout p_layouts[3];
>>> -        VkDescriptorSetLayout ds_layouts[3];
>>> -        VkPipeline pipelines[3][NUM_META_FS_KEYS];
>>> +        VkPipeline depth_only_pipeline[5];
>>>   -        VkRenderPass depth_only_rp[RADV_BLIT_DS_LAYOUT_COUNT];
>>> -        VkPipeline depth_only_pipeline[3];
>>> +        VkPipeline stencil_only_pipeline[5];
>>> +    } blit2d[1 + MAX_SAMPLES_LOG2];
>>>   -        VkRenderPass stencil_only_rp[RADV_BLIT_DS_LAYOUT_COUNT];
>>> -        VkPipeline stencil_only_pipeline[3];
>>> -    } blit2d;
>>> +    VkRenderPass 
>>> blit2d_render_passes[NUM_META_FS_KEYS][RADV_META_DST_LAYOUT_COUNT];
>>> +    VkRenderPass blit2d_depth_only_rp[RADV_BLIT_DS_LAYOUT_COUNT];
>>> +    VkRenderPass blit2d_stencil_only_rp[RADV_BLIT_DS_LAYOUT_COUNT];
>>>         struct {
>>>           VkPipelineLayout img_p_layout;
>>>
>