<div dir="ltr">Any more thoughts on this? Any objections to it going to stable as well (it fixes bugs, but is quite a large change)?<div><br></div><div>Thanks,</div><div>Alex</div></div><div class="gmail_extra"><br><div class="gmail_quote">On 19 April 2018 at 09:27, Matthew Nicholls <span dir="ltr"><<a href="mailto:mnicholls@feralinteractive.com" target="_blank">mnicholls@feralinteractive.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">On 18/04/18 22:56, Dave Airlie wrote:<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
On 18 April 2018 at 00:31, Matthew Nicholls<br>
<<a href="mailto:mnicholls@feralinteractive.com" target="_blank">mnicholls@feralinteractive.co<wbr>m</a>> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Previously before fb077b0728, the LOD parameter was being used in place of the<br>
sample index, which would only copy the first sample to all samples in the<br>
destination image. After that multisample image copies wouldn't copy anything<br>
from my observations.<br>
<br>
Fix this properly by copying each sample in a separate radv_CmdDraw and using a<br>
pipeline with the correct rasterizationSamples for the destination image.<br>
</blockquote>
Have you run CTS on this?<br>
</blockquote></span>
I ran the CTS tests under dEQP-VK.api.copy_and_blit.core<wbr>.* and didn't see any<br>
changes. There were 6 failures both with and without this patch however:<br>
<br>
dEQP-VK.api.copy_and_blit.core<wbr>.resolve_image.{whole_array_<wbr>image,whole_copy_before_resolv<wbr>ing}.{2,4,8}_bit<br>
<br>
This is on an RX 460.<span class="HOEnZb"><font color="#888888"><br>
<br>
Matthew.</font></span><div class="HOEnZb"><div class="h5"><br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
I wrote something similiar (I'm on holidays at the moment so can't<br>
confirm how similiar)<br>
but it failed some CTS tests for me.<br>
<br>
Dave.<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
---<br>
  src/amd/vulkan/radv_meta_blit2<wbr>d.c | 279 ++++++++++++++++++++++++------<wbr>--------<br>
  src/amd/vulkan/radv_private.h     |  18 +--<br>
  2 files changed, 189 insertions(+), 108 deletions(-)<br>
<br>
diff --git a/src/amd/vulkan/radv_meta_bli<wbr>t2d.c b/src/amd/vulkan/radv_meta_bli<wbr>t2d.c<br>
index e163056257..d953241b55 100644<br>
--- a/src/amd/vulkan/radv_meta_bli<wbr>t2d.c<br>
+++ b/src/amd/vulkan/radv_meta_bli<wbr>t2d.c<br>
@@ -100,7 +100,8 @@ blit2d_bind_src(struct radv_cmd_buffer *cmd_buffer,<br>
                  struct radv_meta_blit2d_buffer *src_buf,<br>
                  struct blit2d_src_temps *tmp,<br>
                  enum blit2d_src_type src_type, VkFormat depth_format,<br>
-                VkImageAspectFlagBits aspects)<br>
+                VkImageAspectFlagBits aspects,<br>
+                uint32_t log2_samples)<br>
  {<br>
         struct radv_device *device = cmd_buffer->device;<br>
<br>
@@ -108,7 +109,7 @@ blit2d_bind_src(struct radv_cmd_buffer *cmd_buffer,<br>
                 create_bview(cmd_buffer, src_buf, &tmp->bview, depth_format);<br>
<br>
                 radv_meta_push_descriptor_<wbr>set(cmd_buffer, VK_PIPELINE_BIND_POINT_GRAPHIC<wbr>S,<br>
-                                             device->meta_state.blit2d.p_l<wbr>ayouts[src_type],<br>
+                                             device->meta_state.blit2d[log<wbr>2_samples].p_layouts[src_type]<wbr>,<br>
                                               0, /* set */<br>
                                               1, /* descriptorWriteCount */<br>
                                               (VkWriteDescriptorSet[]) {<br>
@@ -123,7 +124,7 @@ blit2d_bind_src(struct radv_cmd_buffer *cmd_buffer,<br>
                                               });<br>
<br>
                 radv_CmdPushConstants(radv_cm<wbr>d_buffer_to_handle(cmd_buffer)<wbr>,<br>
-                                     device->meta_state.blit2d.p_l<wbr>ayouts[src_type],<br>
+                                     device->meta_state.blit2d[log<wbr>2_samples].p_layouts[src_type]<wbr>,<br>
                                       VK_SHADER_STAGE_FRAGMENT_BIT, 16, 4,<br>
                                       &src_buf->pitch);<br>
         } else {<br>
@@ -131,12 +132,12 @@ blit2d_bind_src(struct radv_cmd_buffer *cmd_buffer,<br>
<br>
                 if (src_type == BLIT2D_SRC_TYPE_IMAGE_3D)<br>
                         radv_CmdPushConstants(radv_cm<wbr>d_buffer_to_handle(cmd_buffer)<wbr>,<br>
-                                             device->meta_state.blit2d.p_l<wbr>ayouts[src_type],<br>
+                                             device->meta_state.blit2d[log<wbr>2_samples].p_layouts[src_type]<wbr>,<br>
                                               VK_SHADER_STAGE_FRAGMENT_BIT, 16, 4,<br>
                                               &src_img->layer);<br>
<br>
                 radv_meta_push_descriptor_<wbr>set(cmd_buffer, VK_PIPELINE_BIND_POINT_GRAPHIC<wbr>S,<br>
-                                             device->meta_state.blit2d.p_l<wbr>ayouts[src_type],<br>
+                                             device->meta_state.blit2d[log<wbr>2_samples].p_layouts[src_type]<wbr>,<br>
                                               0, /* set */<br>
                                               1, /* descriptorWriteCount */<br>
                                               (VkWriteDescriptorSet[]) {<br>
@@ -190,10 +191,11 @@ blit2d_bind_dst(struct radv_cmd_buffer *cmd_buffer,<br>
<br>
  static void<br>
  bind_pipeline(struct radv_cmd_buffer *cmd_buffer,<br>
-              enum blit2d_src_type src_type, unsigned fs_key)<br>
+              enum blit2d_src_type src_type, unsigned fs_key,<br>
+              uint32_t log2_samples)<br>
  {<br>
         VkPipeline pipeline =<br>
-               cmd_buffer->device->meta_stat<wbr>e.blit2d.pipelines[src_type][<wbr>fs_key];<br>
+               cmd_buffer->device->meta_stat<wbr>e.blit2d[log2_samples].pipelin<wbr>es[src_type][fs_key];<br>
<br>
         radv_CmdBindPipeline(radv_<wbr>cmd_buffer_to_handle(cmd_<wbr>buffer),<br>
                              VK_PIPELINE_BIND_POINT_GRAPHIC<wbr>S, pipeline);<br>
@@ -201,10 +203,11 @@ bind_pipeline(struct radv_cmd_buffer *cmd_buffer,<br>
<br>
  static void<br>
  bind_depth_pipeline(struct radv_cmd_buffer *cmd_buffer,<br>
-                   enum blit2d_src_type src_type)<br>
+                   enum blit2d_src_type src_type,<br>
+                   uint32_t log2_samples)<br>
  {<br>
         VkPipeline pipeline =<br>
-               cmd_buffer->device->meta_stat<wbr>e.blit2d.depth_only_pipeline[<wbr>src_type];<br>
+               cmd_buffer->device->meta_stat<wbr>e.blit2d[log2_samples].depth_<wbr>only_pipeline[src_type];<br>
<br>
         radv_CmdBindPipeline(radv_<wbr>cmd_buffer_to_handle(cmd_<wbr>buffer),<br>
                              VK_PIPELINE_BIND_POINT_GRAPHIC<wbr>S, pipeline);<br>
@@ -212,10 +215,11 @@ bind_depth_pipeline(struct radv_cmd_buffer *cmd_buffer,<br>
<br>
  static void<br>
  bind_stencil_pipeline(struct radv_cmd_buffer *cmd_buffer,<br>
-                     enum blit2d_src_type src_type)<br>
+                     enum blit2d_src_type src_type,<br>
+                     uint32_t log2_samples)<br>
  {<br>
         VkPipeline pipeline =<br>
-               cmd_buffer->device->meta_stat<wbr>e.blit2d.stencil_only_pipeline<wbr>[src_type];<br>
+               cmd_buffer->device->meta_stat<wbr>e.blit2d[log2_samples].stencil<wbr>_only_pipeline[src_type];<br>
<br>
         radv_CmdBindPipeline(radv_<wbr>cmd_buffer_to_handle(cmd_<wbr>buffer),<br>
                              VK_PIPELINE_BIND_POINT_GRAPHIC<wbr>S, pipeline);<br>
@@ -227,7 +231,8 @@ radv_meta_blit2d_normal_dst(st<wbr>ruct radv_cmd_buffer *cmd_buffer,<br>
                             struct radv_meta_blit2d_buffer *src_buf,<br>
                             struct radv_meta_blit2d_surf *dst,<br>
                             unsigned num_rects,<br>
-                           struct radv_meta_blit2d_rect *rects, enum blit2d_src_type src_type)<br>
+                           struct radv_meta_blit2d_rect *rects, enum blit2d_src_type src_type,<br>
+                           uint32_t log2_samples)<br>
  {<br>
         struct radv_device *device = cmd_buffer->device;<br>
<br>
@@ -241,7 +246,7 @@ radv_meta_blit2d_normal_dst(st<wbr>ruct radv_cmd_buffer *cmd_buffer,<br>
                         else if (aspect_mask == VK_IMAGE_ASPECT_DEPTH_BIT)<br>
                                 depth_format = vk_format_depth_only(dst->imag<wbr>e->vk_format);<br>
                         struct blit2d_src_temps src_temps;<br>
-                       blit2d_bind_src(cmd_buffer, src_img, src_buf, &src_temps, src_type, depth_format, aspect_mask);<br>
+                       blit2d_bind_src(cmd_buffer, src_img, src_buf, &src_temps, src_type, depth_format, aspect_mask, log2_samples);<br>
<br>
                         struct blit2d_dst_temps dst_temps;<br>
                         blit2d_bind_dst(cmd_buffer, dst, rects[r].dst_x + rects[r].width,<br>
@@ -255,7 +260,7 @@ radv_meta_blit2d_normal_dst(st<wbr>ruct radv_cmd_buffer *cmd_buffer,<br>
                         };<br>
<br>
                         radv_CmdPushConstants(radv_cm<wbr>d_buffer_to_handle(cmd_buffer)<wbr>,<br>
-                                       device->meta_state.blit2d.p_l<wbr>ayouts[src_type],<br>
+                                       device->meta_state.blit2d[log<wbr>2_samples].p_layouts[src_type]<wbr>,<br>
                                         VK_SHADER_STAGE_VERTEX_BIT, 0, 16,<br>
                                         vertex_push_constants);<br>
<br>
@@ -266,7 +271,7 @@ radv_meta_blit2d_normal_dst(st<wbr>ruct radv_cmd_buffer *cmd_buffer,<br>
                                 radv_CmdBeginRenderPass(radv_<wbr>cmd_buffer_to_handle(cmd_buffe<wbr>r),<br>
                                                         &(VkRenderPassBeginInfo) {<br>
                                                                 .sType = VK_STRUCTURE_TYPE_RENDER_PASS_<wbr>BEGIN_INFO,<br>
-                                                                       .renderPass = device->meta_state.blit2d.rend<wbr>er_passes[fs_key][dst_layout],<br>
+                                                                       .renderPass = device->meta_state.blit2d_rend<wbr>er_passes[fs_key][dst_layout],<br>
                                                                         .framebuffer = dst_temps.fb,<br>
                                                                         .renderArea = {<br>
                                                                         .offset = { rects[r].dst_x, rects[r].dst_y, },<br>
@@ -277,13 +282,13 @@ radv_meta_blit2d_normal_dst(st<wbr>ruct radv_cmd_buffer *cmd_buffer,<br>
                                                                                 }, VK_SUBPASS_CONTENTS_INLINE);<br>
<br>
<br>
-                               bind_pipeline(cmd_buffer, src_type, fs_key);<br>
+                               bind_pipeline(cmd_buffer, src_type, fs_key, log2_samples);<br>
                         } else if (aspect_mask == VK_IMAGE_ASPECT_DEPTH_BIT) {<br>
                                 enum radv_blit_ds_layout ds_layout = radv_meta_blit_ds_to_type(dst-<wbr>>current_layout);<br>
                                 radv_CmdBeginRenderPass(radv_<wbr>cmd_buffer_to_handle(cmd_buffe<wbr>r),<br>
                                                         &(VkRenderPassBeginInfo) {<br>
                                                                 .sType = VK_STRUCTURE_TYPE_RENDER_PASS_<wbr>BEGIN_INFO,<br>
-                                                                       .renderPass = device->meta_state.blit2d.dept<wbr>h_only_rp[ds_layout],<br>
+                                                                       .renderPass = device->meta_state.blit2d_dept<wbr>h_only_rp[ds_layout],<br>
                                                                         .framebuffer = dst_temps.fb,<br>
                                                                         .renderArea = {<br>
                                                                         .offset = { rects[r].dst_x, rects[r].dst_y, },<br>
@@ -294,14 +299,14 @@ radv_meta_blit2d_normal_dst(st<wbr>ruct radv_cmd_buffer *cmd_buffer,<br>
                                                                                 }, VK_SUBPASS_CONTENTS_INLINE);<br>
<br>
<br>
-                               bind_depth_pipeline(cmd_buffe<wbr>r, src_type);<br>
+                               bind_depth_pipeline(cmd_buffe<wbr>r, src_type, log2_samples);<br>
<br>
                         } else if (aspect_mask == VK_IMAGE_ASPECT_STENCIL_BIT) {<br>
                                 enum radv_blit_ds_layout ds_layout = radv_meta_blit_ds_to_type(dst-<wbr>>current_layout);<br>
                                 radv_CmdBeginRenderPass(radv_<wbr>cmd_buffer_to_handle(cmd_buffe<wbr>r),<br>
                                                         &(VkRenderPassBeginInfo) {<br>
                                                                 .sType = VK_STRUCTURE_TYPE_RENDER_PASS_<wbr>BEGIN_INFO,<br>
-                                                                       .renderPass = device->meta_state.blit2d.sten<wbr>cil_only_rp[ds_layout],<br>
+                                                                       .renderPass = device->meta_state.blit2d_sten<wbr>cil_only_rp[ds_layout],<br>
                                                                         .framebuffer = dst_temps.fb,<br>
                                                                         .renderArea = {<br>
                                                                         .offset = { rects[r].dst_x, rects[r].dst_y, },<br>
@@ -312,7 +317,7 @@ radv_meta_blit2d_normal_dst(st<wbr>ruct radv_cmd_buffer *cmd_buffer,<br>
                                                                                 }, VK_SUBPASS_CONTENTS_INLINE);<br>
<br>
<br>
-                               bind_stencil_pipeline(cmd_buf<wbr>fer, src_type);<br>
+                               bind_stencil_pipeline(cmd_buf<wbr>fer, src_type, log2_samples);<br>
                         } else<br>
                                 unreachable("Processing blit2d with multiple aspects.");<br>
<br>
@@ -332,7 +337,24 @@ radv_meta_blit2d_normal_dst(st<wbr>ruct radv_cmd_buffer *cmd_buffer,<br>
<br>
<br>
<br>
-                       radv_CmdDraw(radv_cmd_buffer_<wbr>to_handle(cmd_buffer), 3, 1, 0, 0);<br>
+                       if (log2_samples > 0) {<br>
+                               for (uint32_t sample = 0; sample < src_img->image->info.samples; sample++) {<br>
+                                       uint32_t sample_mask = 1 << sample;<br>
+                                       radv_CmdPushConstants(radv_cm<wbr>d_buffer_to_handle(cmd_buffer)<wbr>,<br>
+                                                             device->meta_state.blit2d[log<wbr>2_samples].p_layouts[src_type]<wbr>,<br>
+                                                             VK_SHADER_STAGE_FRAGMENT_BIT, 20, 4,<br>
+                                                             &sample);<br>
+<br>
+                                       radv_CmdPushConstants(radv_cm<wbr>d_buffer_to_handle(cmd_buffer)<wbr>,<br>
+                                                             device->meta_state.blit2d[log<wbr>2_samples].p_layouts[src_type]<wbr>,<br>
+                                                             VK_SHADER_STAGE_FRAGMENT_BIT, 24, 4,<br>
+                                                             &sample_mask);<br>
+<br>
+                                       radv_CmdDraw(radv_cmd_buffer_<wbr>to_handle(cmd_buffer), 3, 1, 0, 0);<br>
+                               }<br>
+                       }<br>
+                       else<br>
+                               radv_CmdDraw(radv_cmd_buffer_<wbr>to_handle(cmd_buffer), 3, 1, 0, 0);<br>
                         radv_CmdEndRenderPass(radv_cm<wbr>d_buffer_to_handle(cmd_buffer)<wbr>);<br>
<br>
                         /* At the point where we emit the draw call, all data from the<br>
@@ -358,7 +380,8 @@ radv_meta_blit2d(struct radv_cmd_buffer *cmd_buffer,<br>
         enum blit2d_src_type src_type = src_buf ? BLIT2D_SRC_TYPE_BUFFER :<br>
                 use_3d ? BLIT2D_SRC_TYPE_IMAGE_3D : BLIT2D_SRC_TYPE_IMAGE;<br>
         radv_meta_blit2d_normal_dst(c<wbr>md_buffer, src_img, src_buf, dst,<br>
-                                   num_rects, rects, src_type);<br>
+                                   num_rects, rects, src_type,<br>
+                                   src_img ? util_logbase2(src_img->image-><wbr>info.samples) : 0);<br>
  }<br>
<br>
  static nir_shader *<br>
@@ -421,11 +444,11 @@ build_nir_vertex_shader(void)<br>
<br>
  typedef nir_ssa_def* (*texel_fetch_build_func)(stru<wbr>ct nir_builder *,<br>
                                                 struct radv_device *,<br>
-                                               nir_ssa_def *, bool);<br>
+                                               nir_ssa_def *, bool, bool);<br>
<br>
  static nir_ssa_def *<br>
  build_nir_texel_fetch(struct nir_builder *b, struct radv_device *device,<br>
-                      nir_ssa_def *tex_pos, bool is_3d)<br>
+                      nir_ssa_def *tex_pos, bool is_3d, bool is_multisampled)<br>
  {<br>
         enum glsl_sampler_dim dim = is_3d ? GLSL_SAMPLER_DIM_3D : GLSL_SAMPLER_DIM_2D;<br>
         const struct glsl_type *sampler_type =<br>
@@ -436,6 +459,7 @@ build_nir_texel_fetch(struct nir_builder *b, struct radv_device *device,<br>
         sampler->data.binding = 0;<br>
<br>
         nir_ssa_def *tex_pos_3d = NULL;<br>
+       nir_intrinsic_instr *sample_idx = NULL;<br>
         if (is_3d) {<br>
                 nir_intrinsic_instr *layer = nir_intrinsic_instr_create(b-><wbr>shader, nir_intrinsic_load_push_consta<wbr>nt);<br>
                 nir_intrinsic_set_base(layer, 16);<br>
@@ -451,13 +475,22 @@ build_nir_texel_fetch(struct nir_builder *b, struct radv_device *device,<br>
                 chans[2] = &layer->dest.ssa;<br>
                 tex_pos_3d = nir_vec(b, chans, 3);<br>
         }<br>
+       if (is_multisampled) {<br>
+               sample_idx = nir_intrinsic_instr_create(b-><wbr>shader, nir_intrinsic_load_push_consta<wbr>nt);<br>
+               nir_intrinsic_set_base(<wbr>sample_idx, 20);<br>
+               nir_intrinsic_set_range(sampl<wbr>e_idx, 4);<br>
+               sample_idx->src[0] = nir_src_for_ssa(nir_imm_int(b, 0));<br>
+               sample_idx->num_components = 1;<br>
+               nir_ssa_dest_init(&sample_<wbr>idx->instr, &sample_idx->dest, 1, 32, "sample_idx");<br>
+               nir_builder_instr_insert(b, &sample_idx->instr);<br>
+       }<br>
         nir_tex_instr *tex = nir_tex_instr_create(b->shader<wbr>, 2);<br>
         tex->sampler_dim = dim;<br>
-       tex->op = nir_texop_txf;<br>
+       tex->op = is_multisampled ? nir_texop_txf_ms : nir_texop_txf;<br>
         tex->src[0].src_type = nir_tex_src_coord;<br>
         tex->src[0].src = nir_src_for_ssa(is_3d ? tex_pos_3d : tex_pos);<br>
-       tex->src[1].src_type = nir_tex_src_lod;<br>
-       tex->src[1].src = nir_src_for_ssa(nir_imm_int(b, 0));<br>
+       tex->src[1].src_type = is_multisampled ? nir_tex_src_ms_index : nir_tex_src_lod;<br>
+       tex->src[1].src = nir_src_for_ssa(is_multisample<wbr>d ? &sample_idx->dest.ssa : nir_imm_int(b, 0));<br>
         tex->dest_type = nir_type_uint;<br>
         tex->is_array = false;<br>
         tex->coord_components = is_3d ? 3 : 2;<br>
@@ -473,7 +506,7 @@ build_nir_texel_fetch(struct nir_builder *b, struct radv_device *device,<br>
<br>
  static nir_ssa_def *<br>
  build_nir_buffer_fetch(struct nir_builder *b, struct radv_device *device,<br>
-                      nir_ssa_def *tex_pos, bool is_3d)<br>
+                      nir_ssa_def *tex_pos, bool is_3d, bool is_multisampled)<br>
  {<br>
         const struct glsl_type *sampler_type =<br>
                 glsl_sampler_type(GLSL_SAMPLE<wbr>R_DIM_BUF, false, false, GLSL_TYPE_UINT);<br>
@@ -519,9 +552,31 @@ static const VkPipelineVertexInputStateCrea<wbr>teInfo normal_vi_create_info = {<br>
         .vertexAttributeDescriptionCo<wbr>unt = 0,<br>
  };<br>
<br>
+static void<br>
+build_nir_store_sample_mask(s<wbr>truct nir_builder *b)<br>
+{<br>
+       nir_intrinsic_instr *sample_mask = nir_intrinsic_instr_create(b-><wbr>shader, nir_intrinsic_load_push_consta<wbr>nt);<br>
+       nir_intrinsic_set_base(<wbr>sample_mask, 24);<br>
+       nir_intrinsic_set_range(sampl<wbr>e_mask, 4);<br>
+       sample_mask->src[0] = nir_src_for_ssa(nir_imm_int(b, 0));<br>
+       sample_mask->num_components = 1;<br>
+       nir_ssa_dest_init(&sample_mas<wbr>k->instr, &sample_mask->dest, 1, 32, "sample_mask");<br>
+       nir_builder_instr_insert(b, &sample_mask->instr);<br>
+<br>
+       const struct glsl_type *sample_mask_out_type = glsl_uint_type();<br>
+<br>
+       nir_variable *sample_mask_out =<br>
+               nir_variable_create(b-><wbr>shader, nir_var_shader_out,<br>
+                                   sample_mask_out_type, "sample_mask_out");<br>
+       sample_mask_out->data.<wbr>location = FRAG_RESULT_SAMPLE_MASK;<br>
+<br>
+       nir_store_var(b, sample_mask_out, &sample_mask->dest.ssa, 0x1);<br>
+}<br>
+<br>
  static nir_shader *<br>
  build_nir_copy_fragment_shader<wbr>(struct radv_device *device,<br>
-                               texel_fetch_build_func txf_func, const char* name, bool is_3d)<br>
+                               texel_fetch_build_func txf_func, const char* name, bool is_3d,<br>
+                               bool is_multisampled)<br>
  {<br>
         const struct glsl_type *vec4 = glsl_vec4_type();<br>
         const struct glsl_type *vec2 = glsl_vector_type(GLSL_TYPE_FLO<wbr>AT, 2);<br>
@@ -538,11 +593,15 @@ build_nir_copy_fragment_shader<wbr>(struct radv_device *device,<br>
                                                       vec4, "f_color");<br>
         color_out->data.location = FRAG_RESULT_DATA0;<br>
<br>
+       if (is_multisampled) {<br>
+               build_nir_store_sample_mask(&<wbr>b);<br>
+       }<br>
+<br>
         nir_ssa_def *pos_int = nir_f2i32(&b, nir_load_var(&b, tex_pos_in));<br>
         unsigned swiz[4] = { 0, 1 };<br>
         nir_ssa_def *tex_pos = nir_swizzle(&b, pos_int, swiz, 2, false);<br>
<br>
-       nir_ssa_def *color = txf_func(&b, device, tex_pos, is_3d);<br>
+       nir_ssa_def *color = txf_func(&b, device, tex_pos, is_3d, is_multisampled);<br>
         nir_store_var(&b, color_out, color, 0xf);<br>
<br>
         return b.shader;<br>
@@ -550,7 +609,8 @@ build_nir_copy_fragment_shader<wbr>(struct radv_device *device,<br>
<br>
  static nir_shader *<br>
  build_nir_copy_fragment_shader<wbr>_depth(struct radv_device *device,<br>
-                                    texel_fetch_build_func txf_func, const char* name, bool is_3d)<br>
+                                    texel_fetch_build_func txf_func, const char* name, bool is_3d,<br>
+                                    bool is_multisampled)<br>
  {<br>
         const struct glsl_type *vec4 = glsl_vec4_type();<br>
         const struct glsl_type *vec2 = glsl_vector_type(GLSL_TYPE_FLO<wbr>AT, 2);<br>
@@ -567,11 +627,15 @@ build_nir_copy_fragment_shader<wbr>_depth(struct radv_device *device,<br>
                                                       vec4, "f_color");<br>
         color_out->data.location = FRAG_RESULT_DEPTH;<br>
<br>
+       if (is_multisampled) {<br>
+               build_nir_store_sample_mask(&<wbr>b);<br>
+       }<br>
+<br>
         nir_ssa_def *pos_int = nir_f2i32(&b, nir_load_var(&b, tex_pos_in));<br>
         unsigned swiz[4] = { 0, 1 };<br>
         nir_ssa_def *tex_pos = nir_swizzle(&b, pos_int, swiz, 2, false);<br>
<br>
-       nir_ssa_def *color = txf_func(&b, device, tex_pos, is_3d);<br>
+       nir_ssa_def *color = txf_func(&b, device, tex_pos, is_3d, is_multisampled);<br>
         nir_store_var(&b, color_out, color, 0x1);<br>
<br>
         return b.shader;<br>
@@ -579,7 +643,8 @@ build_nir_copy_fragment_shader<wbr>_depth(struct radv_device *device,<br>
<br>
  static nir_shader *<br>
  build_nir_copy_fragment_shader<wbr>_stencil(struct radv_device *device,<br>
-                                      texel_fetch_build_func txf_func, const char* name, bool is_3d)<br>
+                                      texel_fetch_build_func txf_func, const char* name, bool is_3d,<br>
+                                      bool is_multisampled)<br>
  {<br>
         const struct glsl_type *vec4 = glsl_vec4_type();<br>
         const struct glsl_type *vec2 = glsl_vector_type(GLSL_TYPE_FLO<wbr>AT, 2);<br>
@@ -596,11 +661,15 @@ build_nir_copy_fragment_shader<wbr>_stencil(struct radv_device *device,<br>
                                                       vec4, "f_color");<br>
         color_out->data.location = FRAG_RESULT_STENCIL;<br>
<br>
+       if (is_multisampled) {<br>
+               build_nir_store_sample_mask(&<wbr>b);<br>
+       }<br>
+<br>
         nir_ssa_def *pos_int = nir_f2i32(&b, nir_load_var(&b, tex_pos_in));<br>
         unsigned swiz[4] = { 0, 1 };<br>
         nir_ssa_def *tex_pos = nir_swizzle(&b, pos_int, swiz, 2, false);<br>
<br>
-       nir_ssa_def *color = txf_func(&b, device, tex_pos, is_3d);<br>
+       nir_ssa_def *color = txf_func(&b, device, tex_pos, is_3d, is_multisampled);<br>
         nir_store_var(&b, color_out, color, 0x1);<br>
<br>
         return b.shader;<br>
@@ -614,45 +683,48 @@ radv_device_finish_meta_blit2d<wbr>_state(struct radv_device *device)<br>
         for(unsigned j = 0; j < NUM_META_FS_KEYS; ++j) {<br>
                 for (unsigned k = 0; k < RADV_META_DST_LAYOUT_COUNT; ++k) {<br>
                         radv_DestroyRenderPass(radv_d<wbr>evice_to_handle(device),<br>
-                                              state->blit2d.render_passes[j]<wbr>[k],<br>
-                                              &state->alloc);<br>
+                                              state->blit2d_render_passes[j]<wbr>[k],<br>
+                                              &state->alloc);<br>
                 }<br>
         }<br>
<br>
         for (enum radv_blit_ds_layout j = RADV_BLIT_DS_LAYOUT_TILE_ENABL<wbr>E; j < RADV_BLIT_DS_LAYOUT_COUNT; j++) {<br>
                 radv_DestroyRenderPass(radv_d<wbr>evice_to_handle(device),<br>
-                                      state->blit2d.depth_only_rp[j]<wbr>, &state->alloc);<br>
+                                      state->blit2d_depth_only_rp[j]<wbr>, &state->alloc);<br>
                 radv_DestroyRenderPass(radv_d<wbr>evice_to_handle(device),<br>
-                                      state->blit2d.stencil_only_rp[<wbr>j], &state->alloc);<br>
+                                      state->blit2d_stencil_only_rp[<wbr>j], &state->alloc);<br>
         }<br>
<br>
-       for (unsigned src = 0; src < BLIT2D_NUM_SRC_TYPES; src++) {<br>
-               radv_DestroyPipelineLayout(ra<wbr>dv_device_to_handle(device),<br>
-                                          state->blit2d.p_layouts[src],<br>
-                                          &state->alloc);<br>
-               radv_DestroyDescriptorSetLayo<wbr>ut(radv_device_to_handle(<wbr>device),<br>
-                                               state->blit2d.ds_layouts[src]<wbr>,<br>
-                                               &state->alloc);<br>
+       for (unsigned log2_samples = 0; log2_samples < 1 + MAX_SAMPLES_LOG2; ++log2_samples) {<br>
+               for (unsigned src = 0; src < BLIT2D_NUM_SRC_TYPES; src++) {<br>
+                       radv_DestroyPipelineLayout(ra<wbr>dv_device_to_handle(device),<br>
+                                                  state->blit2d[log2_samples].p_<wbr>layouts[src],<br>
+                                                  &state->alloc);<br>
+                       radv_DestroyDescriptorSetLayo<wbr>ut(radv_device_to_handle(<wbr>device),<br>
+                                                       state->blit2d[log2_samples].d<wbr>s_layouts[src],<br>
+                                                       &state->alloc);<br>
+<br>
+                       for (unsigned j = 0; j < NUM_META_FS_KEYS; ++j) {<br>
+                               radv_DestroyPipeline(radv_dev<wbr>ice_to_handle(device),<br>
+                                                    state->blit2d[log2_samples].pi<wbr>pelines[src][j],<br>
+                                                    &state->alloc);<br>
+                       }<br>
<br>
-               for (unsigned j = 0; j < NUM_META_FS_KEYS; ++j) {<br>
                         radv_DestroyPipeline(radv_dev<wbr>ice_to_handle(device),<br>
-                                            state->blit2d.pipelines[src][j<wbr>],<br>
+                                            state->blit2d[log2_samples].de<wbr>pth_only_pipeline[src],<br>
+                                            &state->alloc);<br>
+                       radv_DestroyPipeline(radv_dev<wbr>ice_to_handle(device),<br>
+                                            state->blit2d[log2_samples].st<wbr>encil_only_pipeline[src],<br>
                                              &state->alloc);<br>
                 }<br>
-<br>
-               radv_DestroyPipeline(radv_dev<wbr>ice_to_handle(device),<br>
-                                    state->blit2d.depth_only_pipel<wbr>ine[src],<br>
-                                    &state->alloc);<br>
-               radv_DestroyPipeline(radv_dev<wbr>ice_to_handle(device),<br>
-                                    state->blit2d.stencil_only_pip<wbr>eline[src],<br>
-                                    &state->alloc);<br>
         }<br>
  }<br>
<br>
  static VkResult<br>
  blit2d_init_color_pipeline(str<wbr>uct radv_device *device,<br>
                            enum blit2d_src_type src_type,<br>
-                          VkFormat format)<br>
+                          VkFormat format,<br>
+                          uint32_t log2_samples)<br>
  {<br>
         VkResult result;<br>
         unsigned fs_key = radv_format_meta_fs_key(format<wbr>);<br>
@@ -681,7 +753,7 @@ blit2d_init_color_pipeline(str<wbr>uct radv_device *device,<br>
         struct radv_shader_module fs = { .nir = NULL };<br>
<br>
<br>
-       fs.nir = build_nir_copy_fragment_shader<wbr>(device, src_func, name, src_type == BLIT2D_SRC_TYPE_IMAGE_3D);<br>
+       fs.nir = build_nir_copy_fragment_shader<wbr>(device, src_func, name, src_type == BLIT2D_SRC_TYPE_IMAGE_3D, log2_samples > 0);<br>
         vi_create_info = &normal_vi_create_info;<br>
<br>
         struct radv_shader_module vs = {<br>
@@ -705,7 +777,7 @@ blit2d_init_color_pipeline(str<wbr>uct radv_device *device,<br>
         };<br>
<br>
         for (unsigned dst_layout = 0; dst_layout < RADV_META_DST_LAYOUT_COUNT; ++dst_layout) {<br>
-               if (!device-><a href="http://meta_state.blit2d.re">meta_state.blit2d.re</a><wbr>nder_passes[fs_key][dst_layout<wbr>]) {<br>
+               if (!device->meta_state.blit2d_re<wbr>nder_passes[fs_key][dst_layout<wbr>]) {<br>
                         VkImageLayout layout = radv_meta_dst_layout_to_layout<wbr>(dst_layout);<br>
<br>
                         result = radv_CreateRenderPass(radv_dev<wbr>ice_to_handle(device),<br>
@@ -737,7 +809,7 @@ blit2d_init_color_pipeline(str<wbr>uct radv_device *device,<br>
                                                 .pPreserveAttachments = (uint32_t[]) { 0 },<br>
                                                 },<br>
                                                 .dependencyCount = 0,<br>
-                                       }, &device->meta_state.alloc, &device->meta_state.blit2d.ren<wbr>der_passes[fs_key][dst_layout]<wbr>);<br>
+                                       }, &device->meta_state.alloc, &device->meta_state.blit2d_ren<wbr>der_passes[fs_key][dst_layout]<wbr>);<br>
                 }<br>
         }<br>
<br>
@@ -765,7 +837,7 @@ blit2d_init_color_pipeline(str<wbr>uct radv_device *device,<br>
                 },<br>
                 .pMultisampleState = &(VkPipelineMultisampleStateCr<wbr>eateInfo) {<br>
                         .sType = VK_STRUCTURE_TYPE_PIPELINE_MUL<wbr>TISAMPLE_STATE_CREATE_INFO,<br>
-                       .rasterizationSamples = 1,<br>
+                       .rasterizationSamples = 1 << log2_samples,<br>
                         .sampleShadingEnable = false,<br>
                         .pSampleMask = (VkSampleMask[]) { UINT32_MAX },<br>
                 },<br>
@@ -796,8 +868,8 @@ blit2d_init_color_pipeline(str<wbr>uct radv_device *device,<br>
                         },<br>
                 },<br>
                 .flags = 0,<br>
-               .layout = device->meta_state.blit2d.p_la<wbr>youts[src_type],<br>
-               .renderPass = device->meta_state.blit2d.rend<wbr>er_passes[fs_key][0],<br>
+               .layout = device->meta_state.blit2d[log2<wbr>_samples].p_layouts[src_type],<br>
+               .renderPass = device->meta_state.blit2d_rend<wbr>er_passes[fs_key][0],<br>
                 .subpass = 0,<br>
         };<br>
<br>
@@ -809,7 +881,7 @@ blit2d_init_color_pipeline(str<wbr>uct radv_device *device,<br>
                                                radv_pipeline_cache_to_handle(<wbr>&device->meta_state.cache),<br>
                                                &vk_pipeline_info, &radv_pipeline_info,<br>
                                                &device->meta_state.alloc,<br>
-                                              &device->meta_state.blit2d.pip<wbr>elines[src_type][fs_key]);<br>
+                                              &device->meta_state.blit2d[log<wbr>2_samples].pipelines[src_type]<wbr>[fs_key]);<br>
<br>
<br>
         ralloc_free(vs.nir);<br>
@@ -820,7 +892,8 @@ blit2d_init_color_pipeline(str<wbr>uct radv_device *device,<br>
<br>
  static VkResult<br>
  blit2d_init_depth_only_pipelin<wbr>e(struct radv_device *device,<br>
-                               enum blit2d_src_type src_type)<br>
+                               enum blit2d_src_type src_type,<br>
+                               uint32_t log2_samples)<br>
  {<br>
         VkResult result;<br>
         const char *name;<br>
@@ -847,7 +920,7 @@ blit2d_init_depth_only_pipelin<wbr>e(struct radv_device *device,<br>
         const VkPipelineVertexInputStateCrea<wbr>teInfo *vi_create_info;<br>
         struct radv_shader_module fs = { .nir = NULL };<br>
<br>
-       fs.nir = build_nir_copy_fragment_shader<wbr>_depth(device, src_func, name, src_type == BLIT2D_SRC_TYPE_IMAGE_3D);<br>
+       fs.nir = build_nir_copy_fragment_shader<wbr>_depth(device, src_func, name, src_type == BLIT2D_SRC_TYPE_IMAGE_3D, log2_samples > 0);<br>
         vi_create_info = &normal_vi_create_info;<br>
<br>
         struct radv_shader_module vs = {<br>
@@ -871,7 +944,7 @@ blit2d_init_depth_only_pipelin<wbr>e(struct radv_device *device,<br>
         };<br>
<br>
         for (enum radv_blit_ds_layout ds_layout = RADV_BLIT_DS_LAYOUT_TILE_ENABL<wbr>E; ds_layout < RADV_BLIT_DS_LAYOUT_COUNT; ds_layout++) {<br>
-               if (!device-><a href="http://meta_state.blit2d.de">meta_state.blit2d.de</a><wbr>pth_only_rp[ds_layout]) {<br>
+               if (!device->meta_state.blit2d_de<wbr>pth_only_rp[ds_layout]) {<br>
                         VkImageLayout layout = radv_meta_blit_ds_to_layout(ds<wbr>_layout);<br>
                         result = radv_CreateRenderPass(radv_dev<wbr>ice_to_handle(device),<br>
                                                        &(VkRenderPassCreateInfo) {<br>
@@ -899,7 +972,7 @@ blit2d_init_depth_only_pipelin<wbr>e(struct radv_device *device,<br>
                                                                        .pPreserveAttachments = (uint32_t[]) { 0 },<br>
                                                                },<br>
                                                                .dependencyCount = 0,<br>
-                                                       }, &device->meta_state.alloc, &device->meta_state.blit2d.dep<wbr>th_only_rp[ds_layout]);<br>
+                                                       }, &device->meta_state.alloc, &device->meta_state.blit2d_dep<wbr>th_only_rp[ds_layout]);<br>
                 }<br>
         }<br>
<br>
@@ -927,7 +1000,7 @@ blit2d_init_depth_only_pipelin<wbr>e(struct radv_device *device,<br>
                 },<br>
                 .pMultisampleState = &(VkPipelineMultisampleStateCr<wbr>eateInfo) {<br>
                         .sType = VK_STRUCTURE_TYPE_PIPELINE_MUL<wbr>TISAMPLE_STATE_CREATE_INFO,<br>
-                       .rasterizationSamples = 1,<br>
+                       .rasterizationSamples = 1 << log2_samples,<br>
                         .sampleShadingEnable = false,<br>
                         .pSampleMask = (VkSampleMask[]) { UINT32_MAX },<br>
                 },<br>
@@ -958,8 +1031,8 @@ blit2d_init_depth_only_pipelin<wbr>e(struct radv_device *device,<br>
                         },<br>
                 },<br>
                 .flags = 0,<br>
-               .layout = device->meta_state.blit2d.p_la<wbr>youts[src_type],<br>
-               .renderPass = device->meta_state.blit2d.dept<wbr>h_only_rp[0],<br>
+               .layout = device->meta_state.blit2d[log2<wbr>_samples].p_layouts[src_type],<br>
+               .renderPass = device->meta_state.blit2d_dept<wbr>h_only_rp[0],<br>
                 .subpass = 0,<br>
         };<br>
<br>
@@ -971,7 +1044,7 @@ blit2d_init_depth_only_pipelin<wbr>e(struct radv_device *device,<br>
                                                radv_pipeline_cache_to_handle(<wbr>&device->meta_state.cache),<br>
                                                &vk_pipeline_info, &radv_pipeline_info,<br>
                                                &device->meta_state.alloc,<br>
-                                              &device->meta_state.blit2d.dep<wbr>th_only_pipeline[src_type]);<br>
+                                              &device->meta_state.blit2d[log<wbr>2_samples].depth_only_pipeline<wbr>[src_type]);<br>
<br>
<br>
         ralloc_free(vs.nir);<br>
@@ -982,7 +1055,8 @@ blit2d_init_depth_only_pipelin<wbr>e(struct radv_device *device,<br>
<br>
  static VkResult<br>
  blit2d_init_stencil_only_pipel<wbr>ine(struct radv_device *device,<br>
-                                 enum blit2d_src_type src_type)<br>
+                                 enum blit2d_src_type src_type,<br>
+                                 uint32_t log2_samples)<br>
  {<br>
         VkResult result;<br>
         const char *name;<br>
@@ -1009,7 +1083,7 @@ blit2d_init_stencil_only_pipel<wbr>ine(struct radv_device *device,<br>
         const VkPipelineVertexInputStateCrea<wbr>teInfo *vi_create_info;<br>
         struct radv_shader_module fs = { .nir = NULL };<br>
<br>
-       fs.nir = build_nir_copy_fragment_shader<wbr>_stencil(device, src_func, name, src_type == BLIT2D_SRC_TYPE_IMAGE_3D);<br>
+       fs.nir = build_nir_copy_fragment_shader<wbr>_stencil(device, src_func, name, src_type == BLIT2D_SRC_TYPE_IMAGE_3D, log2_samples > 0);<br>
         vi_create_info = &normal_vi_create_info;<br>
<br>
         struct radv_shader_module vs = {<br>
@@ -1033,7 +1107,7 @@ blit2d_init_stencil_only_pipel<wbr>ine(struct radv_device *device,<br>
         };<br>
<br>
         for (enum radv_blit_ds_layout ds_layout = RADV_BLIT_DS_LAYOUT_TILE_ENABL<wbr>E; ds_layout < RADV_BLIT_DS_LAYOUT_COUNT; ds_layout++) {<br>
-               if (!device-><a href="http://meta_state.blit2d.st">meta_state.blit2d.st</a><wbr>encil_only_rp[ds_layout]) {<br>
+               if (!device->meta_state.blit2d_st<wbr>encil_only_rp[ds_layout]) {<br>
                         VkImageLayout layout = radv_meta_blit_ds_to_layout(ds<wbr>_layout);<br>
                         result = radv_CreateRenderPass(radv_dev<wbr>ice_to_handle(device),<br>
                                                        &(VkRenderPassCreateInfo) {<br>
@@ -1061,7 +1135,7 @@ blit2d_init_stencil_only_pipel<wbr>ine(struct radv_device *device,<br>
                                                                        .pPreserveAttachments = (uint32_t[]) { 0 },<br>
                                                                },<br>
                                                                .dependencyCount = 0,<br>
-                                                      }, &device->meta_state.alloc, &device->meta_state.blit2d.ste<wbr>ncil_only_rp[ds_layout]);<br>
+                                                      }, &device->meta_state.alloc, &device->meta_state.blit2d_ste<wbr>ncil_only_rp[ds_layout]);<br>
                 }<br>
         }<br>
<br>
@@ -1089,7 +1163,7 @@ blit2d_init_stencil_only_pipel<wbr>ine(struct radv_device *device,<br>
                 },<br>
                 .pMultisampleState = &(VkPipelineMultisampleStateCr<wbr>eateInfo) {<br>
                         .sType = VK_STRUCTURE_TYPE_PIPELINE_MUL<wbr>TISAMPLE_STATE_CREATE_INFO,<br>
-                       .rasterizationSamples = 1,<br>
+                       .rasterizationSamples = 1 << log2_samples,<br>
                         .sampleShadingEnable = false,<br>
                         .pSampleMask = (VkSampleMask[]) { UINT32_MAX },<br>
                 },<br>
@@ -1136,8 +1210,8 @@ blit2d_init_stencil_only_pipel<wbr>ine(struct radv_device *device,<br>
                         },<br>
                 },<br>
                 .flags = 0,<br>
-               .layout = device->meta_state.blit2d.p_la<wbr>youts[src_type],<br>
-               .renderPass = device->meta_state.blit2d.sten<wbr>cil_only_rp[0],<br>
+               .layout = device->meta_state.blit2d[log2<wbr>_samples].p_layouts[src_type],<br>
+               .renderPass = device->meta_state.blit2d_sten<wbr>cil_only_rp[0],<br>
                 .subpass = 0,<br>
         };<br>
<br>
@@ -1149,7 +1223,7 @@ blit2d_init_stencil_only_pipel<wbr>ine(struct radv_device *device,<br>
                                                radv_pipeline_cache_to_handle(<wbr>&device->meta_state.cache),<br>
                                                &vk_pipeline_info, &radv_pipeline_info,<br>
                                                &device->meta_state.alloc,<br>
-                                              &device->meta_state.blit2d.ste<wbr>ncil_only_pipeline[src_type]);<br>
+                                              &device->meta_state.blit2d[log<wbr>2_samples].stencil_only_pipeli<wbr>ne[src_type]);<br>
<br>
<br>
         ralloc_free(vs.nir);<br>
@@ -1175,15 +1249,16 @@ static VkFormat pipeline_formats[] = {<br>
<br>
  static VkResult<br>
  meta_blit2d_create_pipe_layout<wbr>(struct radv_device *device,<br>
-                              int idx)<br>
+                              int idx,<br>
+                              uint32_t log2_samples)<br>
  {<br>
         VkResult result;<br>
         VkDescriptorType desc_type = (idx == BLIT2D_SRC_TYPE_BUFFER) ? VK_DESCRIPTOR_TYPE_UNIFORM_TEX<wbr>EL_BUFFER : VK_DESCRIPTOR_TYPE_SAMPLED_IMA<wbr>GE;<br>
         const VkPushConstantRange push_constant_ranges[] = {<br>
                 {VK_SHADER_STAGE_VERTEX_BIT, 0, 16},<br>
-               {VK_SHADER_STAGE_FRAGMENT_<wbr>BIT, 16, 4},<br>
+               {VK_SHADER_STAGE_FRAGMENT_<wbr>BIT, 16, 12},<br>
         };<br>
-       int num_push_constant_range = (idx != BLIT2D_SRC_TYPE_IMAGE) ? 2 : 1;<br>
+       int num_push_constant_range = (idx != BLIT2D_SRC_TYPE_IMAGE || log2_samples > 0) ? 2 : 1;<br>
<br>
         result = radv_CreateDescriptorSetLayout<wbr>(radv_device_to_handle(device)<wbr>,<br>
                                                 &(VkDescriptorSetLayoutCreate<wbr>Info) {<br>
@@ -1199,7 +1274,7 @@ meta_blit2d_create_pipe_layout<wbr>(struct radv_device *device,<br>
                                                                 .pImmutableSamplers = NULL<br>
                                                         },<br>
                                                         }<br>
-                                               }, &device->meta_state.alloc, &device->meta_state.blit2d.ds_<wbr>layouts[idx]);<br>
+                                               }, &device->meta_state.alloc, &device->meta_state.blit2d[log<wbr>2_samples].ds_layouts[idx]);<br>
         if (result != VK_SUCCESS)<br>
                 goto fail;<br>
<br>
@@ -1207,11 +1282,11 @@ meta_blit2d_create_pipe_layout<wbr>(struct radv_device *device,<br>
                                            &(VkPipelineLayoutCreateInfo) {<br>
                                                    .sType = VK_STRUCTURE_TYPE_PIPELINE_LAY<wbr>OUT_CREATE_INFO,<br>
                                                            .setLayoutCount = 1,<br>
-                                                          .pSetLayouts = &device->meta_state.blit2d.ds_<wbr>layouts[idx],<br>
+                                                          .pSetLayouts = &device->meta_state.blit2d[log<wbr>2_samples].ds_layouts[idx],<br>
                                                            .pushConstantRangeCount = num_push_constant_range,<br>
                                                            .pPushConstantRanges = push_constant_ranges,<br>
                                                            },<br>
-                                          &device->meta_state.alloc, &device->meta_state.blit2d.p_l<wbr>ayouts[idx]);<br>
+                                          &device->meta_state.alloc, &device->meta_state.blit2d[log<wbr>2_samples].p_layouts[idx]);<br>
         if (result != VK_SUCCESS)<br>
                 goto fail;<br>
         return VK_SUCCESS;<br>
@@ -1225,27 +1300,33 @@ radv_device_init_meta_blit2d_s<wbr>tate(struct radv_device *device)<br>
         VkResult result;<br>
         bool create_3d = device->physical_device->rad_i<wbr>nfo.chip_class >= GFX9;<br>
<br>
-       for (unsigned src = 0; src < BLIT2D_NUM_SRC_TYPES; src++) {<br>
-               if (src == BLIT2D_SRC_TYPE_IMAGE_3D && !create_3d)<br>
-                       continue;<br>
+       for (unsigned log2_samples = 0; log2_samples < 1 + MAX_SAMPLES_LOG2; log2_samples++) {<br>
+               for (unsigned src = 0; src < BLIT2D_NUM_SRC_TYPES; src++) {<br>
+                       if (src == BLIT2D_SRC_TYPE_IMAGE_3D && !create_3d)<br>
+                               continue;<br>
<br>
-               result = meta_blit2d_create_pipe_layout<wbr>(device, src);<br>
-               if (result != VK_SUCCESS)<br>
-                       goto fail;<br>
+                       /* Don't need to handle copies between buffers and multisample images. */<br>
+                       if (src == BLIT2D_SRC_TYPE_BUFFER && log2_samples > 0)<br>
+                               continue;<br>
<br>
-               for (unsigned j = 0; j < ARRAY_SIZE(pipeline_formats); ++j) {<br>
-                       result = blit2d_init_color_pipeline(dev<wbr>ice, src, pipeline_formats[j]);<br>
+                       result = meta_blit2d_create_pipe_layout<wbr>(device, src, log2_samples);<br>
                         if (result != VK_SUCCESS)<br>
                                 goto fail;<br>
-               }<br>
<br>
-               result = blit2d_init_depth_only_pipelin<wbr>e(device, src);<br>
-               if (result != VK_SUCCESS)<br>
-                       goto fail;<br>
+                       for (unsigned j = 0; j < ARRAY_SIZE(pipeline_formats); ++j) {<br>
+                               result = blit2d_init_color_pipeline(dev<wbr>ice, src, pipeline_formats[j], log2_samples);<br>
+                               if (result != VK_SUCCESS)<br>
+                                       goto fail;<br>
+                       }<br>
+<br>
+                       result = blit2d_init_depth_only_pipelin<wbr>e(device, src, log2_samples);<br>
+                       if (result != VK_SUCCESS)<br>
+                               goto fail;<br>
<br>
-               result = blit2d_init_stencil_only_pipel<wbr>ine(device, src);<br>
-               if (result != VK_SUCCESS)<br>
-                       goto fail;<br>
+                       result = blit2d_init_stencil_only_pipel<wbr>ine(device, src, log2_samples);<br>
+                       if (result != VK_SUCCESS)<br>
+                               goto fail;<br>
+               }<br>
         }<br>
<br>
         return VK_SUCCESS;<br>
diff --git a/src/amd/vulkan/radv_private.<wbr>h b/src/amd/vulkan/radv_private.<wbr>h<br>
index 1869604e9e..3c548fe059 100644<br>
--- a/src/amd/vulkan/radv_private.<wbr>h<br>
+++ b/src/amd/vulkan/radv_private.<wbr>h<br>
@@ -462,18 +462,18 @@ struct radv_meta_state {<br>
         } blit;<br>
<br>
         struct {<br>
-               VkRenderPass render_passes[NUM_META_FS_KEYS<wbr>][RADV_META_DST_LAYOUT_COUNT];<br>
+               VkPipelineLayout p_layouts[5];<br>
+               VkDescriptorSetLayout ds_layouts[5];<br>
+               VkPipeline pipelines[5][NUM_META_FS_KEYS]<wbr>;<br>
<br>
-               VkPipelineLayout p_layouts[3];<br>
-               VkDescriptorSetLayout ds_layouts[3];<br>
-               VkPipeline pipelines[3][NUM_META_FS_KEYS]<wbr>;<br>
+               VkPipeline depth_only_pipeline[5];<br>
<br>
-               VkRenderPass depth_only_rp[RADV_BLIT_DS_LAY<wbr>OUT_COUNT];<br>
-               VkPipeline depth_only_pipeline[3];<br>
+               VkPipeline stencil_only_pipeline[5];<br>
+       } blit2d[1 + MAX_SAMPLES_LOG2];<br>
<br>
-               VkRenderPass stencil_only_rp[RADV_BLIT_DS_L<wbr>AYOUT_COUNT];<br>
-               VkPipeline stencil_only_pipeline[3];<br>
-       } blit2d;<br>
+       VkRenderPass blit2d_render_passes[NUM_META_<wbr>FS_KEYS][RADV_META_DST_LAYOUT_<wbr>COUNT];<br>
+       VkRenderPass blit2d_depth_only_rp[RADV_BLIT<wbr>_DS_LAYOUT_COUNT];<br>
+       VkRenderPass blit2d_stencil_only_rp[RADV_BL<wbr>IT_DS_LAYOUT_COUNT];<br>
<br>
         struct {<br>
                 VkPipelineLayout                          img_p_layout;<br>
--<br>
2.14.3<br>
<br>
</blockquote></blockquote>
<br>
</div></div></blockquote></div><br></div>