[Mesa-dev] [PATCH v3] radv: fix multisample image copies

Samuel Pitoiset samuel.pitoiset at gmail.com
Fri Apr 27 16:34:06 UTC 2018


From: Matthew Nicholls <mnicholls at 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.

v3: - reset is_multisampled for 3D images (Samuel)
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 at lists.freedesktop.org>
---

I have figured out this just before pushing the patch... Not sure why
Polaris isn't affected, but using nir_texop_txf_ms for 3D images is
clearly wrong. I didn't run CTS on Vega yet, but I'm not going to push
this patch before next week (probably on Monday).

Matthew, if you have a Vega around, please confirm it still works.

Thanks!

 src/amd/vulkan/radv_meta_blit2d.c | 293 ++++++++++++++++++++----------
 src/amd/vulkan/radv_private.h     |  18 +-
 2 files changed, 202 insertions(+), 109 deletions(-)

diff --git a/src/amd/vulkan/radv_meta_blit2d.c b/src/amd/vulkan/radv_meta_blit2d.c
index e163056257..79c1fe2c9e 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);
@@ -680,8 +753,11 @@ blit2d_init_color_pipeline(struct radv_device *device,
 	const VkPipelineVertexInputStateCreateInfo *vi_create_info;
 	struct radv_shader_module fs = { .nir = NULL };
 
+	bool is_multisampled = log2_samples > 0;
+	if (src_type == BLIT2D_SRC_TYPE_IMAGE_3D)
+		is_multisampled = false;
 
-	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, is_multisampled);
 	vi_create_info = &normal_vi_create_info;
 
 	struct radv_shader_module vs = {
@@ -705,7 +781,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 +813,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 +841,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 +872,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 +885,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 +896,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 +924,11 @@ 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);
+	bool is_multisampled = log2_samples > 0;
+	if (src_type == BLIT2D_SRC_TYPE_IMAGE_3D)
+		is_multisampled = false;
+
+	fs.nir = build_nir_copy_fragment_shader_depth(device, src_func, name, src_type == BLIT2D_SRC_TYPE_IMAGE_3D, is_multisampled);
 	vi_create_info = &normal_vi_create_info;
 
 	struct radv_shader_module vs = {
@@ -871,7 +952,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 +980,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 +1008,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 +1039,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 +1052,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 +1063,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 +1091,11 @@ 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);
+	bool is_multisampled = log2_samples > 0;
+	if (src_type == BLIT2D_SRC_TYPE_IMAGE_3D)
+		is_multisampled = false;
+
+	fs.nir = build_nir_copy_fragment_shader_stencil(device, src_func, name, src_type == BLIT2D_SRC_TYPE_IMAGE_3D, is_multisampled);
 	vi_create_info = &normal_vi_create_info;
 
 	struct radv_shader_module vs = {
@@ -1033,7 +1119,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 +1147,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 +1175,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 +1222,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 +1235,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 +1261,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 +1286,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 +1294,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 +1312,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 883342ede8..5d67271961 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;
-- 
2.17.0



More information about the mesa-dev mailing list