vk/formats: Document new meaning of anv_format::cpp
[mesa.git] / src / vulkan / meta.c
index f2e0a161027f2c5586ef5843eadac0582a21a93e..2167d29da6a5c476c4ea46a9c0ace88735cd34d1 100644 (file)
@@ -28,7 +28,7 @@
 #include <fcntl.h>
 
 #include "private.h"
-#include "glsl_helpers.h"
+#include "meta-spirv.h"
 
 static void
 anv_device_init_meta_clear_state(struct anv_device *device)
@@ -123,58 +123,63 @@ anv_device_init_meta_clear_state(struct anv_device *device)
       .frontFace = VK_FRONT_FACE_CCW
    };
 
+   VkPipelineCbStateCreateInfo cb_create_info = {
+      .sType = VK_STRUCTURE_TYPE_PIPELINE_CB_STATE_CREATE_INFO,
+      .pNext = &rs_create_info,
+      .attachmentCount = 1,
+      .pAttachments = (VkPipelineCbAttachmentState []) {
+         { .channelWriteMask = VK_CHANNEL_A_BIT |
+              VK_CHANNEL_R_BIT | VK_CHANNEL_G_BIT | VK_CHANNEL_B_BIT },
+      }
+   };
+
    anv_pipeline_create((VkDevice) device,
-                       &(VkGraphicsPipelineCreateInfo) {
-                          .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
-                          .pNext = &rs_create_info,
-                          .flags = 0,
-                          .layout = 0
-                       },
-                       &(struct anv_pipeline_create_info) {
-                          .use_repclear = true,
-                          .disable_viewport = true,
-                          .use_rectlist = true
-                       },
-                       &device->clear_state.pipeline);
+      &(VkGraphicsPipelineCreateInfo) {
+         .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
+         .pNext = &cb_create_info,
+         .flags = 0,
+         .layout = 0
+      },
+      &(struct anv_pipeline_create_info) {
+         .use_repclear = true,
+         .disable_viewport = true,
+         .use_rectlist = true
+      },
+      &device->meta_state.clear.pipeline);
 
    anv_DestroyObject((VkDevice) device, VK_OBJECT_TYPE_SHADER, fs);
-
-   anv_CreateDynamicRasterState((VkDevice) device,
-                                &(VkDynamicRsStateCreateInfo) {
-                                   .sType = VK_STRUCTURE_TYPE_DYNAMIC_RS_STATE_CREATE_INFO,
-                                },
-                                &device->clear_state.rs_state);
 }
 
 #define NUM_VB_USED 2
 struct anv_saved_state {
-   struct anv_bindings bindings;
-   struct anv_bindings *old_bindings;
+   struct anv_vertex_binding old_vertex_bindings[NUM_VB_USED];
+   struct anv_descriptor_set *old_descriptor_set0;
    struct anv_pipeline *old_pipeline;
+   VkDynamicCbState cb_state;
 };
 
 static void
 anv_cmd_buffer_save(struct anv_cmd_buffer *cmd_buffer,
                     struct anv_saved_state *state)
 {
-   state->old_bindings = cmd_buffer->bindings;
-   cmd_buffer->bindings = &state->bindings;
    state->old_pipeline = cmd_buffer->pipeline;
-
-   /* Initialize render targets for the meta bindings. */
-   anv_cmd_buffer_fill_render_targets(cmd_buffer);
+   state->old_descriptor_set0 = cmd_buffer->descriptors[0].set;
+   memcpy(state->old_vertex_bindings, cmd_buffer->vertex_bindings,
+          sizeof(state->old_vertex_bindings));
 }
 
 static void
 anv_cmd_buffer_restore(struct anv_cmd_buffer *cmd_buffer,
                        const struct anv_saved_state *state)
 {
-   cmd_buffer->bindings = state->old_bindings;
    cmd_buffer->pipeline = state->old_pipeline;
+   cmd_buffer->descriptors[0].set = state->old_descriptor_set0;
+   memcpy(cmd_buffer->vertex_bindings, state->old_vertex_bindings,
+          sizeof(state->old_vertex_bindings));
 
    cmd_buffer->vb_dirty |= (1 << NUM_VB_USED) - 1;
-   cmd_buffer->dirty |= ANV_CMD_BUFFER_PIPELINE_DIRTY |
-                        ANV_CMD_BUFFER_DESCRIPTOR_SET_DIRTY;
+   cmd_buffer->dirty |= ANV_CMD_BUFFER_PIPELINE_DIRTY;
+   cmd_buffer->descriptors_dirty |= VK_SHADER_STAGE_VERTEX_BIT;
 }
 
 struct vue_header {
@@ -246,30 +251,41 @@ anv_cmd_buffer_clear(struct anv_cmd_buffer *cmd_buffer,
    anv_cmd_buffer_save(cmd_buffer, &saved_state);
 
    anv_CmdBindVertexBuffers((VkCmdBuffer) cmd_buffer, 0, 2,
-                            (VkBuffer[]) {
-                               (VkBuffer) &vertex_buffer,
-                               (VkBuffer) &vertex_buffer
-                            },
-                            (VkDeviceSize[]) {
-                               0,
-                               sizeof(vertex_data)
-                            });
-
-   if ((VkPipeline) cmd_buffer->pipeline != device->clear_state.pipeline)
+      (VkBuffer[]) {
+         (VkBuffer) &vertex_buffer,
+         (VkBuffer) &vertex_buffer
+      },
+      (VkDeviceSize[]) {
+         0,
+         sizeof(vertex_data)
+      });
+
+   if ((VkPipeline) cmd_buffer->pipeline != device->meta_state.clear.pipeline)
       anv_CmdBindPipeline((VkCmdBuffer) cmd_buffer,
-                          VK_PIPELINE_BIND_POINT_GRAPHICS, device->clear_state.pipeline);
+                          VK_PIPELINE_BIND_POINT_GRAPHICS,
+                          device->meta_state.clear.pipeline);
 
    /* We don't need anything here, only set if not already set. */
    if (cmd_buffer->rs_state == NULL)
       anv_CmdBindDynamicStateObject((VkCmdBuffer) cmd_buffer,
                                     VK_STATE_BIND_POINT_RASTER,
-                                    device->clear_state.rs_state);
+                                    device->meta_state.shared.rs_state);
 
    if (cmd_buffer->vp_state == NULL)
       anv_CmdBindDynamicStateObject((VkCmdBuffer) cmd_buffer,
                                     VK_STATE_BIND_POINT_VIEWPORT,
                                     cmd_buffer->framebuffer->vp_state);
 
+   if (cmd_buffer->ds_state == NULL)
+      anv_CmdBindDynamicStateObject((VkCmdBuffer) cmd_buffer,
+                                    VK_STATE_BIND_POINT_DEPTH_STENCIL,
+                                    device->meta_state.shared.ds_state);
+
+   if (cmd_buffer->cb_state == NULL)
+      anv_CmdBindDynamicStateObject((VkCmdBuffer) cmd_buffer,
+                                    VK_STATE_BIND_POINT_COLOR_BLEND,
+                                    device->meta_state.shared.cb_state);
+
    anv_CmdDraw((VkCmdBuffer) cmd_buffer, 0, 3, 0, pass->num_clear_layers);
 
    /* Restore API state */
@@ -307,10 +323,10 @@ anv_device_init_meta_blit_state(struct anv_device *device)
    VkShader fs = GLSL_VK_SHADER(device, FRAGMENT,
       out vec4 f_color;
       in vec4 v_tex_coord;
-      layout(set = 0, index = 0) uniform sampler2D u_tex;
+      layout(set = 0, binding = 0) uniform sampler2D u_tex;
       void main()
       {
-         f_color = texture2D(u_tex, v_tex_coord.xy);
+         f_color = texture(u_tex, v_tex_coord.xy);
       }
    );
 
@@ -393,17 +409,15 @@ anv_device_init_meta_blit_state(struct anv_device *device)
       }
    };
    anv_CreateDescriptorSetLayout((VkDevice) device, &ds_layout_info,
-                                 &device->blit_state.ds_layout);
-
-   VkPipelineLayoutCreateInfo pipeline_layout_info = {
-      .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
-      .descriptorSetCount = 1,
-      .pSetLayouts = &device->blit_state.ds_layout,
-   };
+                                 &device->meta_state.blit.ds_layout);
 
-   VkPipelineLayout pipeline_layout;
-   anv_CreatePipelineLayout((VkDevice) device, &pipeline_layout_info,
-                            &pipeline_layout);
+   anv_CreatePipelineLayout((VkDevice) device,
+      &(VkPipelineLayoutCreateInfo) {
+         .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
+         .descriptorSetCount = 1,
+         .pSetLayouts = &device->meta_state.blit.ds_layout,
+      },
+      &device->meta_state.blit.pipeline_layout);
 
    VkPipelineRsStateCreateInfo rs_create_info = {
       .sType = VK_STRUCTURE_TYPE_PIPELINE_RS_STATE_CREATE_INFO,
@@ -415,11 +429,21 @@ anv_device_init_meta_blit_state(struct anv_device *device)
       .frontFace = VK_FRONT_FACE_CCW
    };
 
+   VkPipelineCbStateCreateInfo cb_create_info = {
+      .sType = VK_STRUCTURE_TYPE_PIPELINE_CB_STATE_CREATE_INFO,
+      .pNext = &rs_create_info,
+      .attachmentCount = 1,
+      .pAttachments = (VkPipelineCbAttachmentState []) {
+         { .channelWriteMask = VK_CHANNEL_A_BIT |
+              VK_CHANNEL_R_BIT | VK_CHANNEL_G_BIT | VK_CHANNEL_B_BIT },
+      }
+   };
+
    VkGraphicsPipelineCreateInfo pipeline_info = {
       .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
-      .pNext = &rs_create_info,
+      .pNext = &cb_create_info,
       .flags = 0,
-      .layout = pipeline_layout,
+      .layout = device->meta_state.blit.pipeline_layout,
    };
 
    anv_pipeline_create((VkDevice) device, &pipeline_info,
@@ -430,16 +454,10 @@ anv_device_init_meta_blit_state(struct anv_device *device)
                           .disable_vs = true,
                           .use_rectlist = true
                        },
-                       &device->blit_state.pipeline);
+                       &device->meta_state.blit.pipeline);
 
    anv_DestroyObject((VkDevice) device, VK_OBJECT_TYPE_SHADER, vs);
    anv_DestroyObject((VkDevice) device, VK_OBJECT_TYPE_SHADER, fs);
-
-   anv_CreateDynamicRasterState((VkDevice) device,
-                                &(VkDynamicRsStateCreateInfo) {
-                                   .sType = VK_STRUCTURE_TYPE_DYNAMIC_RS_STATE_CREATE_INFO,
-                                 },
-                                &device->blit_state.rs_state);
 }
 
 static void
@@ -450,16 +468,25 @@ meta_prepare_blit(struct anv_cmd_buffer *cmd_buffer,
 
    anv_cmd_buffer_save(cmd_buffer, saved_state);
 
-   if ((VkPipeline) cmd_buffer->pipeline != device->blit_state.pipeline)
+   if ((VkPipeline) cmd_buffer->pipeline != device->meta_state.blit.pipeline)
       anv_CmdBindPipeline((VkCmdBuffer) cmd_buffer,
                           VK_PIPELINE_BIND_POINT_GRAPHICS,
-                          device->blit_state.pipeline);
+                          device->meta_state.blit.pipeline);
 
    /* We don't need anything here, only set if not already set. */
    if (cmd_buffer->rs_state == NULL)
       anv_CmdBindDynamicStateObject((VkCmdBuffer) cmd_buffer,
                                     VK_STATE_BIND_POINT_RASTER,
-                                    device->blit_state.rs_state);
+                                    device->meta_state.shared.rs_state);
+   if (cmd_buffer->ds_state == NULL)
+      anv_CmdBindDynamicStateObject((VkCmdBuffer) cmd_buffer,
+                                    VK_STATE_BIND_POINT_DEPTH_STENCIL,
+                                    device->meta_state.shared.ds_state);
+
+   saved_state->cb_state = (VkDynamicCbState) cmd_buffer->cb_state;
+   anv_CmdBindDynamicStateObject((VkCmdBuffer) cmd_buffer,
+                                 VK_STATE_BIND_POINT_COLOR_BLEND,
+                                 device->meta_state.shared.cb_state);
 }
 
 struct blit_region {
@@ -533,81 +560,80 @@ meta_emit_blit(struct anv_cmd_buffer *cmd_buffer,
    };
 
    anv_CmdBindVertexBuffers((VkCmdBuffer) cmd_buffer, 0, 2,
-                            (VkBuffer[]) {
-                               (VkBuffer) &vertex_buffer,
-                               (VkBuffer) &vertex_buffer
-                            },
-                            (VkDeviceSize[]) {
-                               0,
-                               sizeof(struct vue_header),
-                            });
+      (VkBuffer[]) {
+         (VkBuffer) &vertex_buffer,
+         (VkBuffer) &vertex_buffer
+      },
+      (VkDeviceSize[]) {
+         0,
+         sizeof(struct vue_header),
+      });
 
    uint32_t count;
    VkDescriptorSet set;
    anv_AllocDescriptorSets((VkDevice) device, 0 /* pool */,
                            VK_DESCRIPTOR_SET_USAGE_ONE_SHOT,
-                           1, &device->blit_state.ds_layout, &set, &count);
+                           1, &device->meta_state.blit.ds_layout, &set, &count);
    anv_UpdateDescriptors((VkDevice) device, set, 1,
-                         (const void * []) {
-                            &(VkUpdateImages) {
-                               .sType = VK_STRUCTURE_TYPE_UPDATE_IMAGES,
-                               .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
-                               .binding = 0,
-                               .count = 1,
-                               .pImageViews = (VkImageViewAttachInfo[]) {
-                                  {
-                                     .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_ATTACH_INFO,
-                                     .view = (VkImageView) src,
-                                     .layout = VK_IMAGE_LAYOUT_GENERAL,
-                                  }
-                               }
-                            }
-                         });
-
-   VkFramebufferCreateInfo fb_info = {
-      .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
-      .colorAttachmentCount = 1,
-      .pColorAttachments = (VkColorAttachmentBindInfo[]) {
-         {
-            .view = (VkColorAttachmentView) dest,
-            .layout = VK_IMAGE_LAYOUT_GENERAL
+      (const void * []) {
+         &(VkUpdateImages) {
+            .sType = VK_STRUCTURE_TYPE_UPDATE_IMAGES,
+            .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
+            .binding = 0,
+            .count = 1,
+            .pImageViews = (VkImageViewAttachInfo[]) {
+               {
+                  .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_ATTACH_INFO,
+                  .view = (VkImageView) src,
+                  .layout = VK_IMAGE_LAYOUT_GENERAL,
+               }
+            }
          }
-      },
-      .pDepthStencilAttachment = NULL,
-      .sampleCount = 1,
-      .width = dest->extent.width,
-      .height = dest->extent.height,
-      .layers = 1
-   };
+      });
 
    struct anv_framebuffer *fb;
-   anv_CreateFramebuffer((VkDevice) device, &fb_info, (VkFramebuffer *)&fb);
-
-   VkRenderPassCreateInfo pass_info = {
-      .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
-      .renderArea = { { 0, 0 }, { dest->extent.width, dest->extent.height } },
-      .colorAttachmentCount = 1,
-      .extent = { 0, },
-      .sampleCount = 1,
-      .layers = 1,
-      .pColorFormats = (VkFormat[]) { dest->format },
-      .pColorLayouts = (VkImageLayout[]) { VK_IMAGE_LAYOUT_GENERAL },
-      .pColorLoadOps = (VkAttachmentLoadOp[]) { VK_ATTACHMENT_LOAD_OP_LOAD },
-      .pColorStoreOps = (VkAttachmentStoreOp[]) { VK_ATTACHMENT_STORE_OP_STORE },
-      .pColorLoadClearValues = (VkClearColor[]) {
-         { .color = { .floatColor = { 1.0, 0.0, 0.0, 1.0 } }, .useRawValue = false }
-      },
-      .depthStencilFormat = VK_FORMAT_UNDEFINED,
-   };
+   anv_CreateFramebuffer((VkDevice) device,
+      &(VkFramebufferCreateInfo) {
+         .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
+         .colorAttachmentCount = 1,
+         .pColorAttachments = (VkColorAttachmentBindInfo[]) {
+            {
+               .view = (VkColorAttachmentView) dest,
+               .layout = VK_IMAGE_LAYOUT_GENERAL
+            }
+         },
+         .pDepthStencilAttachment = NULL,
+         .sampleCount = 1,
+         .width = dest->extent.width,
+         .height = dest->extent.height,
+         .layers = 1
+      }, (VkFramebuffer *)&fb);
+
 
    VkRenderPass pass;
-   anv_CreateRenderPass((VkDevice )device, &pass_info, &pass);
+   anv_CreateRenderPass((VkDevice )device,
+      &(VkRenderPassCreateInfo) {
+         .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
+         .renderArea = { { 0, 0 }, { dest->extent.width, dest->extent.height } },
+         .colorAttachmentCount = 1,
+         .extent = { 0, },
+         .sampleCount = 1,
+         .layers = 1,
+         .pColorFormats = (VkFormat[]) { dest->format },
+         .pColorLayouts = (VkImageLayout[]) { VK_IMAGE_LAYOUT_GENERAL },
+         .pColorLoadOps = (VkAttachmentLoadOp[]) { VK_ATTACHMENT_LOAD_OP_LOAD },
+         .pColorStoreOps = (VkAttachmentStoreOp[]) { VK_ATTACHMENT_STORE_OP_STORE },
+         .pColorLoadClearValues = (VkClearColor[]) {
+            { .color = { .floatColor = { 1.0, 0.0, 0.0, 1.0 } }, .useRawValue = false }
+         },
+         .depthStencilFormat = VK_FORMAT_UNDEFINED,
+      }, &pass);
 
    anv_CmdBeginRenderPass((VkCmdBuffer) cmd_buffer,
-                          &(VkRenderPassBegin) {
-                             .renderPass = pass,
-                             .framebuffer = (VkFramebuffer) fb,
-                          });
+      &(VkRenderPassBegin) {
+         .renderPass = pass,
+         .framebuffer = (VkFramebuffer) fb,
+      });
 
    anv_CmdBindDynamicStateObject((VkCmdBuffer) cmd_buffer,
                                  VK_STATE_BIND_POINT_VIEWPORT, fb->vp_state);
@@ -619,6 +645,14 @@ meta_emit_blit(struct anv_cmd_buffer *cmd_buffer,
    anv_CmdDraw((VkCmdBuffer) cmd_buffer, 0, 3, 0, 1);
 
    anv_CmdEndRenderPass((VkCmdBuffer) cmd_buffer, pass);
+
+   /* At the point where we emit the draw call, all data from the
+    * descriptor sets, etc. has been used.  We are free to delete it.
+    */
+   anv_DestroyObject((VkDevice) device, VK_OBJECT_TYPE_DESCRIPTOR_SET, set);
+   anv_DestroyObject((VkDevice) device, VK_OBJECT_TYPE_FRAMEBUFFER,
+                     (VkFramebuffer) fb);
+   anv_DestroyObject((VkDevice) device, VK_OBJECT_TYPE_RENDER_PASS, pass);
 }
 
 static void
@@ -626,6 +660,111 @@ meta_finish_blit(struct anv_cmd_buffer *cmd_buffer,
                  const struct anv_saved_state *saved_state)
 {
    anv_cmd_buffer_restore(cmd_buffer, saved_state);
+   anv_CmdBindDynamicStateObject((VkCmdBuffer) cmd_buffer,
+                                 VK_STATE_BIND_POINT_COLOR_BLEND,
+                                 saved_state->cb_state);
+}
+
+static VkFormat
+vk_format_for_cpp(int cpp)
+{
+   switch (cpp) {
+   case 1: return VK_FORMAT_R8_UINT;
+   case 2: return VK_FORMAT_R8G8_UINT;
+   case 3: return VK_FORMAT_R8G8B8_UINT;
+   case 4: return VK_FORMAT_R8G8B8A8_UINT;
+   case 6: return VK_FORMAT_R16G16B16_UINT;
+   case 8: return VK_FORMAT_R16G16B16A16_UINT;
+   case 12: return VK_FORMAT_R32G32B32_UINT;
+   case 16: return VK_FORMAT_R32G32B32A32_UINT;
+   default:
+      unreachable("Invalid format cpp");
+   }
+}
+
+static void
+do_buffer_copy(struct anv_cmd_buffer *cmd_buffer,
+               struct anv_bo *src, uint64_t src_offset,
+               struct anv_bo *dest, uint64_t dest_offset,
+               int width, int height, VkFormat copy_format)
+{
+   VkDevice vk_device = (VkDevice)cmd_buffer->device;
+
+   VkImageCreateInfo image_info = {
+      .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
+      .imageType = VK_IMAGE_TYPE_2D,
+      .format = copy_format,
+      .extent = {
+         .width = width,
+         .height = height,
+         .depth = 1,
+      },
+      .mipLevels = 1,
+      .arraySize = 1,
+      .samples = 1,
+      .tiling = VK_IMAGE_TILING_LINEAR,
+      .usage = VK_IMAGE_USAGE_SAMPLED_BIT,
+      .flags = 0,
+   };
+
+   struct anv_image *src_image, *dest_image;
+   anv_CreateImage(vk_device, &image_info, (VkImage *)&src_image);
+   anv_CreateImage(vk_device, &image_info, (VkImage *)&dest_image);
+
+   /* We could use a vk call to bind memory, but that would require
+    * creating a dummy memory object etc. so there's really no point.
+    */
+   src_image->bo = src;
+   src_image->offset = src_offset;
+   dest_image->bo = dest;
+   dest_image->offset = dest_offset;
+
+   struct anv_surface_view src_view;
+   anv_image_view_init(&src_view, cmd_buffer->device,
+      &(VkImageViewCreateInfo) {
+         .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
+         .image = (VkImage)src_image,
+         .viewType = VK_IMAGE_VIEW_TYPE_2D,
+         .format = copy_format,
+         .channels = {
+            VK_CHANNEL_SWIZZLE_R,
+            VK_CHANNEL_SWIZZLE_G,
+            VK_CHANNEL_SWIZZLE_B,
+            VK_CHANNEL_SWIZZLE_A
+         },
+         .subresourceRange = {
+            .aspect = VK_IMAGE_ASPECT_COLOR,
+            .baseMipLevel = 0,
+            .mipLevels = 1,
+            .baseArraySlice = 0,
+            .arraySize = 1
+         },
+         .minLod = 0
+      },
+      cmd_buffer);
+
+   struct anv_surface_view dest_view;
+   anv_color_attachment_view_init(&dest_view, cmd_buffer->device,
+      &(VkColorAttachmentViewCreateInfo) {
+         .sType = VK_STRUCTURE_TYPE_COLOR_ATTACHMENT_VIEW_CREATE_INFO,
+         .image = (VkImage)dest_image,
+         .format = copy_format,
+         .mipLevel = 0,
+         .baseArraySlice = 0,
+         .arraySize = 1,
+      },
+      cmd_buffer);
+
+   meta_emit_blit(cmd_buffer,
+                  &src_view,
+                  (VkOffset3D) { 0, 0, 0 },
+                  (VkExtent3D) { width, height, 1 },
+                  &dest_view,
+                  (VkOffset3D) { 0, 0, 0 },
+                  (VkExtent3D) { width, height, 1 });
+
+   anv_DestroyObject(vk_device, VK_OBJECT_TYPE_IMAGE, (VkImage) src_image);
+   anv_DestroyObject(vk_device, VK_OBJECT_TYPE_IMAGE, (VkImage) dest_image);
 }
 
 void anv_CmdCopyBuffer(
@@ -635,7 +774,74 @@ void anv_CmdCopyBuffer(
     uint32_t                                    regionCount,
     const VkBufferCopy*                         pRegions)
 {
-   stub();
+   struct anv_cmd_buffer *cmd_buffer = (struct anv_cmd_buffer *)cmdBuffer;
+   struct anv_buffer *src_buffer = (struct anv_buffer *)srcBuffer;
+   struct anv_buffer *dest_buffer = (struct anv_buffer *)destBuffer;
+   struct anv_saved_state saved_state;
+
+   meta_prepare_blit(cmd_buffer, &saved_state);
+
+   for (unsigned r = 0; r < regionCount; r++) {
+      uint64_t src_offset = src_buffer->offset + pRegions[r].srcOffset;
+      uint64_t dest_offset = dest_buffer->offset + pRegions[r].destOffset;
+      uint64_t copy_size = pRegions[r].copySize;
+
+      /* First, we compute the biggest format that can be used with the
+       * given offsets and size.
+       */
+      int cpp = 16;
+
+      int fs = ffs(src_offset) - 1;
+      if (fs != -1)
+         cpp = MIN2(cpp, 1 << fs);
+      assert(src_offset % cpp == 0);
+
+      fs = ffs(dest_offset) - 1;
+      if (fs != -1)
+         cpp = MIN2(cpp, 1 << fs);
+      assert(dest_offset % cpp == 0);
+
+      fs = ffs(pRegions[r].copySize) - 1;
+      if (fs != -1)
+         cpp = MIN2(cpp, 1 << fs);
+      assert(pRegions[r].copySize % cpp == 0);
+
+      VkFormat copy_format = vk_format_for_cpp(cpp);
+
+      /* This is maximum possible width/height our HW can handle */
+      uint64_t max_surface_dim = 1 << 14;
+
+      /* First, we make a bunch of max-sized copies */
+      uint64_t max_copy_size = max_surface_dim * max_surface_dim * cpp;
+      while (copy_size > max_copy_size) {
+         do_buffer_copy(cmd_buffer, src_buffer->bo, src_offset,
+                        dest_buffer->bo, dest_offset,
+                        max_surface_dim, max_surface_dim, copy_format);
+         copy_size -= max_copy_size;
+         src_offset += max_copy_size;
+         dest_offset += max_copy_size;
+      }
+
+      uint64_t height = copy_size / (max_surface_dim * cpp);
+      assert(height < max_surface_dim);
+      if (height != 0) {
+         uint64_t rect_copy_size = height * max_surface_dim * cpp;
+         do_buffer_copy(cmd_buffer, src_buffer->bo, src_offset,
+                        dest_buffer->bo, dest_offset,
+                        max_surface_dim, height, copy_format);
+         copy_size -= rect_copy_size;
+         src_offset += rect_copy_size;
+         dest_offset += rect_copy_size;
+      }
+
+      if (copy_size != 0) {
+         do_buffer_copy(cmd_buffer, src_buffer->bo, src_offset,
+                        dest_buffer->bo, dest_offset,
+                        copy_size / cpp, 1, copy_format);
+      }
+   }
+
+   meta_finish_blit(cmd_buffer, &saved_state);
 }
 
 void anv_CmdCopyImage(
@@ -647,7 +853,59 @@ void anv_CmdCopyImage(
     uint32_t                                    regionCount,
     const VkImageCopy*                          pRegions)
 {
-   stub();
+   struct anv_cmd_buffer *cmd_buffer = (struct anv_cmd_buffer *)cmdBuffer;
+   struct anv_image *src_image = (struct anv_image *)srcImage;
+   struct anv_saved_state saved_state;
+
+   meta_prepare_blit(cmd_buffer, &saved_state);
+
+   for (unsigned r = 0; r < regionCount; r++) {
+      struct anv_surface_view src_view;
+      anv_image_view_init(&src_view, cmd_buffer->device,
+         &(VkImageViewCreateInfo) {
+            .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
+            .image = srcImage,
+            .viewType = VK_IMAGE_VIEW_TYPE_2D,
+            .format = src_image->format,
+            .channels = {
+               VK_CHANNEL_SWIZZLE_R,
+               VK_CHANNEL_SWIZZLE_G,
+               VK_CHANNEL_SWIZZLE_B,
+               VK_CHANNEL_SWIZZLE_A
+            },
+            .subresourceRange = {
+               .aspect = pRegions[r].srcSubresource.aspect,
+               .baseMipLevel = pRegions[r].srcSubresource.mipLevel,
+               .mipLevels = 1,
+               .baseArraySlice = pRegions[r].srcSubresource.arraySlice,
+               .arraySize = 1
+            },
+            .minLod = 0
+         },
+         cmd_buffer);
+
+      struct anv_surface_view dest_view;
+      anv_color_attachment_view_init(&dest_view, cmd_buffer->device,
+         &(VkColorAttachmentViewCreateInfo) {
+            .sType = VK_STRUCTURE_TYPE_COLOR_ATTACHMENT_VIEW_CREATE_INFO,
+            .image = destImage,
+            .format = src_image->format,
+            .mipLevel = pRegions[r].destSubresource.mipLevel,
+            .baseArraySlice = pRegions[r].destSubresource.arraySlice,
+            .arraySize = 1,
+         },
+         cmd_buffer);
+
+      meta_emit_blit(cmd_buffer,
+                     &src_view,
+                     pRegions[r].srcOffset,
+                     pRegions[r].extent,
+                     &dest_view,
+                     pRegions[r].destOffset,
+                     pRegions[r].extent);
+   }
+
+   meta_finish_blit(cmd_buffer, &saved_state);
 }
 
 void anv_CmdBlitImage(
@@ -659,7 +917,60 @@ void anv_CmdBlitImage(
     uint32_t                                    regionCount,
     const VkImageBlit*                          pRegions)
 {
-   stub();
+   struct anv_cmd_buffer *cmd_buffer = (struct anv_cmd_buffer *)cmdBuffer;
+   struct anv_image *src_image = (struct anv_image *)srcImage;
+   struct anv_image *dest_image = (struct anv_image *)destImage;
+   struct anv_saved_state saved_state;
+
+   meta_prepare_blit(cmd_buffer, &saved_state);
+
+   for (unsigned r = 0; r < regionCount; r++) {
+      struct anv_surface_view src_view;
+      anv_image_view_init(&src_view, cmd_buffer->device,
+         &(VkImageViewCreateInfo) {
+            .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
+            .image = srcImage,
+            .viewType = VK_IMAGE_VIEW_TYPE_2D,
+            .format = src_image->format,
+            .channels = {
+               VK_CHANNEL_SWIZZLE_R,
+               VK_CHANNEL_SWIZZLE_G,
+               VK_CHANNEL_SWIZZLE_B,
+               VK_CHANNEL_SWIZZLE_A
+            },
+            .subresourceRange = {
+               .aspect = pRegions[r].srcSubresource.aspect,
+               .baseMipLevel = pRegions[r].srcSubresource.mipLevel,
+               .mipLevels = 1,
+               .baseArraySlice = pRegions[r].srcSubresource.arraySlice,
+               .arraySize = 1
+            },
+            .minLod = 0
+         },
+         cmd_buffer);
+
+      struct anv_surface_view dest_view;
+      anv_color_attachment_view_init(&dest_view, cmd_buffer->device,
+         &(VkColorAttachmentViewCreateInfo) {
+            .sType = VK_STRUCTURE_TYPE_COLOR_ATTACHMENT_VIEW_CREATE_INFO,
+            .image = destImage,
+            .format = dest_image->format,
+            .mipLevel = pRegions[r].destSubresource.mipLevel,
+            .baseArraySlice = pRegions[r].destSubresource.arraySlice,
+            .arraySize = 1,
+         },
+         cmd_buffer);
+
+      meta_emit_blit(cmd_buffer,
+                     &src_view,
+                     pRegions[r].srcOffset,
+                     pRegions[r].srcExtent,
+                     &dest_view,
+                     pRegions[r].destOffset,
+                     pRegions[r].destExtent);
+   }
+
+   meta_finish_blit(cmd_buffer, &saved_state);
 }
 
 void anv_CmdCopyBufferToImage(
@@ -670,7 +981,88 @@ void anv_CmdCopyBufferToImage(
     uint32_t                                    regionCount,
     const VkBufferImageCopy*                    pRegions)
 {
-   stub();
+   struct anv_cmd_buffer *cmd_buffer = (struct anv_cmd_buffer *)cmdBuffer;
+   VkDevice vk_device = (VkDevice) cmd_buffer->device;
+   struct anv_buffer *src_buffer = (struct anv_buffer *)srcBuffer;
+   struct anv_image *dest_image = (struct anv_image *)destImage;
+   struct anv_saved_state saved_state;
+
+   meta_prepare_blit(cmd_buffer, &saved_state);
+
+   for (unsigned r = 0; r < regionCount; r++) {
+      struct anv_image *src_image;
+      anv_CreateImage(vk_device,
+         &(VkImageCreateInfo) {
+            .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
+            .imageType = VK_IMAGE_TYPE_2D,
+            .format = dest_image->format,
+            .extent = {
+               .width = pRegions[r].imageExtent.width,
+               .height = pRegions[r].imageExtent.height,
+               .depth = 1,
+            },
+            .mipLevels = 1,
+            .arraySize = 1,
+            .samples = 1,
+            .tiling = VK_IMAGE_TILING_LINEAR,
+            .usage = VK_IMAGE_USAGE_SAMPLED_BIT,
+            .flags = 0,
+         }, (VkImage *)&src_image);
+
+      /* We could use a vk call to bind memory, but that would require
+       * creating a dummy memory object etc. so there's really no point.
+       */
+      src_image->bo = src_buffer->bo;
+      src_image->offset = src_buffer->offset + pRegions[r].bufferOffset;
+
+      struct anv_surface_view src_view;
+      anv_image_view_init(&src_view, cmd_buffer->device,
+         &(VkImageViewCreateInfo) {
+            .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
+            .image = (VkImage)src_image,
+            .viewType = VK_IMAGE_VIEW_TYPE_2D,
+            .format = dest_image->format,
+            .channels = {
+               VK_CHANNEL_SWIZZLE_R,
+               VK_CHANNEL_SWIZZLE_G,
+               VK_CHANNEL_SWIZZLE_B,
+               VK_CHANNEL_SWIZZLE_A
+            },
+            .subresourceRange = {
+               .aspect = pRegions[r].imageSubresource.aspect,
+               .baseMipLevel = 0,
+               .mipLevels = 1,
+               .baseArraySlice = 0,
+               .arraySize = 1
+            },
+            .minLod = 0
+         },
+         cmd_buffer);
+
+      struct anv_surface_view dest_view;
+      anv_color_attachment_view_init(&dest_view, cmd_buffer->device,
+         &(VkColorAttachmentViewCreateInfo) {
+            .sType = VK_STRUCTURE_TYPE_COLOR_ATTACHMENT_VIEW_CREATE_INFO,
+            .image = (VkImage)dest_image,
+            .format = dest_image->format,
+            .mipLevel = pRegions[r].imageSubresource.mipLevel,
+            .baseArraySlice = pRegions[r].imageSubresource.arraySlice,
+            .arraySize = 1,
+         },
+         cmd_buffer);
+
+      meta_emit_blit(cmd_buffer,
+                     &src_view,
+                     (VkOffset3D) { 0, 0, 0 },
+                     pRegions[r].imageExtent,
+                     &dest_view,
+                     pRegions[r].imageOffset,
+                     pRegions[r].imageExtent);
+
+      anv_DestroyObject(vk_device, VK_OBJECT_TYPE_IMAGE, (VkImage) src_image);
+   }
+
+   meta_finish_blit(cmd_buffer, &saved_state);
 }
 
 void anv_CmdCopyImageToBuffer(
@@ -690,49 +1082,48 @@ void anv_CmdCopyImageToBuffer(
    meta_prepare_blit(cmd_buffer, &saved_state);
 
    for (unsigned r = 0; r < regionCount; r++) {
-      VkImageViewCreateInfo src_view_info = {
-         .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
-         .image = srcImage,
-         .viewType = VK_IMAGE_VIEW_TYPE_2D,
-         .format = src_image->format,
-         .channels = {
-            VK_CHANNEL_SWIZZLE_R,
-            VK_CHANNEL_SWIZZLE_G,
-            VK_CHANNEL_SWIZZLE_B,
-            VK_CHANNEL_SWIZZLE_A
-         },
-         .subresourceRange = {
-            .aspect = pRegions[r].imageSubresource.aspect,
-            .baseMipLevel = pRegions[r].imageSubresource.mipLevel,
-            .mipLevels = 1,
-            .baseArraySlice = pRegions[r].imageSubresource.arraySlice,
-            .arraySize = 1
-         },
-         .minLod = 0
-      };
-
-      VkImageView src_view;
-      anv_CreateImageView(vk_device, &src_view_info, &src_view);
-
-      VkImageCreateInfo dest_image_info = {
-         .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
-         .imageType = VK_IMAGE_TYPE_2D,
-         .format = src_image->format,
-         .extent = {
-            .width = pRegions[r].imageExtent.width,
-            .height = pRegions[r].imageExtent.height,
-            .depth = 1,
+      struct anv_surface_view src_view;
+      anv_image_view_init(&src_view, cmd_buffer->device,
+         &(VkImageViewCreateInfo) {
+            .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
+            .image = srcImage,
+            .viewType = VK_IMAGE_VIEW_TYPE_2D,
+            .format = src_image->format,
+            .channels = {
+               VK_CHANNEL_SWIZZLE_R,
+               VK_CHANNEL_SWIZZLE_G,
+               VK_CHANNEL_SWIZZLE_B,
+               VK_CHANNEL_SWIZZLE_A
+            },
+            .subresourceRange = {
+               .aspect = pRegions[r].imageSubresource.aspect,
+               .baseMipLevel = pRegions[r].imageSubresource.mipLevel,
+               .mipLevels = 1,
+               .baseArraySlice = pRegions[r].imageSubresource.arraySlice,
+               .arraySize = 1
+            },
+            .minLod = 0
          },
-         .mipLevels = 1,
-         .arraySize = 1,
-         .samples = 1,
-         .tiling = VK_IMAGE_TILING_LINEAR,
-         .usage = VK_IMAGE_USAGE_SAMPLED_BIT,
-         .flags = 0,
-      };
+         cmd_buffer);
 
       struct anv_image *dest_image;
-      anv_CreateImage(vk_device, &dest_image_info, (VkImage *)&dest_image);
+      anv_CreateImage(vk_device,
+         &(VkImageCreateInfo) {
+            .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
+            .imageType = VK_IMAGE_TYPE_2D,
+            .format = src_image->format,
+            .extent = {
+               .width = pRegions[r].imageExtent.width,
+               .height = pRegions[r].imageExtent.height,
+               .depth = 1,
+            },
+            .mipLevels = 1,
+            .arraySize = 1,
+            .samples = 1,
+            .tiling = VK_IMAGE_TILING_LINEAR,
+            .usage = VK_IMAGE_USAGE_SAMPLED_BIT,
+            .flags = 0,
+         }, (VkImage *)&dest_image);
 
       /* We could use a vk call to bind memory, but that would require
        * creating a dummy memory object etc. so there's really no point.
@@ -740,25 +1131,27 @@ void anv_CmdCopyImageToBuffer(
       dest_image->bo = dest_buffer->bo;
       dest_image->offset = dest_buffer->offset + pRegions[r].bufferOffset;
 
-      VkColorAttachmentViewCreateInfo dest_view_info = {
-         .sType = VK_STRUCTURE_TYPE_COLOR_ATTACHMENT_VIEW_CREATE_INFO,
-         .image = (VkImage)dest_image,
-         .format = src_image->format,
-         .mipLevel = 0,
-         .baseArraySlice = 0,
-         .arraySize = 1,
-      };
-
-      VkColorAttachmentView dest_view;
-      anv_CreateColorAttachmentView(vk_device, &dest_view_info, &dest_view);
+      struct anv_surface_view dest_view;
+      anv_color_attachment_view_init(&dest_view, cmd_buffer->device,
+         &(VkColorAttachmentViewCreateInfo) {
+            .sType = VK_STRUCTURE_TYPE_COLOR_ATTACHMENT_VIEW_CREATE_INFO,
+            .image = (VkImage)dest_image,
+            .format = src_image->format,
+            .mipLevel = 0,
+            .baseArraySlice = 0,
+            .arraySize = 1,
+         },
+         cmd_buffer);
 
       meta_emit_blit(cmd_buffer,
-                     (struct anv_surface_view *)src_view,
+                     &src_view,
                      pRegions[r].imageOffset,
                      pRegions[r].imageExtent,
-                     (struct anv_surface_view *)dest_view,
+                     &dest_view,
                      (VkOffset3D) { 0, 0, 0 },
                      pRegions[r].imageExtent);
+
+      anv_DestroyObject(vk_device, VK_OBJECT_TYPE_IMAGE, (VkImage) dest_image);
    }
 
    meta_finish_blit(cmd_buffer, &saved_state);
@@ -834,4 +1227,46 @@ anv_device_init_meta(struct anv_device *device)
 {
    anv_device_init_meta_clear_state(device);
    anv_device_init_meta_blit_state(device);
+
+   anv_CreateDynamicRasterState((VkDevice) device,
+      &(VkDynamicRsStateCreateInfo) {
+         .sType = VK_STRUCTURE_TYPE_DYNAMIC_RS_STATE_CREATE_INFO,
+      },
+      &device->meta_state.shared.rs_state);
+
+   anv_CreateDynamicColorBlendState((VkDevice) device,
+      &(VkDynamicCbStateCreateInfo) {
+         .sType = VK_STRUCTURE_TYPE_DYNAMIC_CB_STATE_CREATE_INFO
+      },
+      &device->meta_state.shared.cb_state);
+
+   anv_CreateDynamicDepthStencilState((VkDevice) device,
+      &(VkDynamicDsStateCreateInfo) {
+         .sType = VK_STRUCTURE_TYPE_DYNAMIC_DS_STATE_CREATE_INFO
+      },
+      &device->meta_state.shared.ds_state);
+}
+
+void
+anv_device_finish_meta(struct anv_device *device)
+{
+   /* Clear */
+   anv_DestroyObject((VkDevice) device, VK_OBJECT_TYPE_PIPELINE,
+                     device->meta_state.clear.pipeline);
+
+   /* Blit */
+   anv_DestroyObject((VkDevice) device, VK_OBJECT_TYPE_PIPELINE,
+                     device->meta_state.blit.pipeline);
+   anv_DestroyObject((VkDevice) device, VK_OBJECT_TYPE_PIPELINE_LAYOUT,
+                     device->meta_state.blit.pipeline_layout);
+   anv_DestroyObject((VkDevice) device, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT,
+                     device->meta_state.blit.ds_layout);
+
+   /* Shared */
+   anv_DestroyObject((VkDevice) device, VK_OBJECT_TYPE_DYNAMIC_RS_STATE,
+                     device->meta_state.shared.rs_state);
+   anv_DestroyObject((VkDevice) device, VK_OBJECT_TYPE_DYNAMIC_CB_STATE,
+                     device->meta_state.shared.cb_state);
+   anv_DestroyObject((VkDevice) device, VK_OBJECT_TYPE_DYNAMIC_DS_STATE,
+                     device->meta_state.shared.ds_state);
 }