zink: set primitive restart cap
[mesa.git] / src / gallium / drivers / zink / zink_blit.c
index 9319630761c8faa0e2ec7231770c0ab5950d8654..96824c8a049e8a8970fb7eed83af0720926ec7a7 100644 (file)
@@ -4,14 +4,18 @@
 #include "zink_screen.h"
 
 #include "util/u_blitter.h"
-#include "util/u_format.h"
+#include "util/u_surface.h"
+#include "util/format/u_format.h"
 
 static bool
 blit_resolve(struct zink_context *ctx, const struct pipe_blit_info *info)
 {
-   if (info->mask != PIPE_MASK_RGBA ||
+   if (util_format_get_mask(info->dst.format) != info->mask ||
+       util_format_get_mask(info->src.format) != info->mask ||
+       util_format_is_depth_or_stencil(info->dst.format) ||
        info->scissor_enable ||
-       info->alpha_blend)
+       info->alpha_blend ||
+       info->render_condition_enable)
       return false;
 
    struct zink_resource *src = zink_resource(info->src.resource);
@@ -66,9 +70,19 @@ blit_resolve(struct zink_context *ctx, const struct pipe_blit_info *info)
 static bool
 blit_native(struct zink_context *ctx, const struct pipe_blit_info *info)
 {
-   if (info->mask != PIPE_MASK_RGBA ||
+   if (util_format_get_mask(info->dst.format) != info->mask ||
+       util_format_get_mask(info->src.format) != info->mask ||
        info->scissor_enable ||
-       info->alpha_blend)
+       info->alpha_blend ||
+       info->render_condition_enable)
+      return false;
+
+   if (util_format_is_depth_or_stencil(info->dst.format) &&
+       info->dst.format != info->src.format)
+      return false;
+
+   /* vkCmdBlitImage must not be used for multisampled source or destination images. */
+   if (info->src.resource->nr_samples > 1 || info->dst.resource->nr_samples > 1)
       return false;
 
    struct zink_resource *src = zink_resource(info->src.resource);
@@ -83,13 +97,35 @@ blit_native(struct zink_context *ctx, const struct pipe_blit_info *info)
    zink_batch_reference_resoure(batch, src);
    zink_batch_reference_resoure(batch, dst);
 
-   if (src->layout != VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL)
-      zink_resource_barrier(batch->cmdbuf, src, src->aspect,
-                            VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
+   if (src == dst) {
+      /* The Vulkan 1.1 specification says the following about valid usage
+       * of vkCmdBlitImage:
+       *
+       * "srcImageLayout must be VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR,
+       *  VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL or VK_IMAGE_LAYOUT_GENERAL"
+       *
+       * and:
+       *
+       * "dstImageLayout must be VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR,
+       *  VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL or VK_IMAGE_LAYOUT_GENERAL"
+       *
+       * Since we cant have the same image in two states at the same time,
+       * we're effectively left with VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR or
+       * VK_IMAGE_LAYOUT_GENERAL. And since this isn't a present-related
+       * operation, VK_IMAGE_LAYOUT_GENERAL seems most appropriate.
+       */
+      if (src->layout != VK_IMAGE_LAYOUT_GENERAL)
+         zink_resource_barrier(batch->cmdbuf, src, src->aspect,
+                               VK_IMAGE_LAYOUT_GENERAL);
+   } else {
+      if (src->layout != VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL)
+         zink_resource_barrier(batch->cmdbuf, src, src->aspect,
+                               VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
 
-   if (dst->layout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
-      zink_resource_barrier(batch->cmdbuf, dst, dst->aspect,
-                            VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
+      if (dst->layout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
+         zink_resource_barrier(batch->cmdbuf, dst, dst->aspect,
+                               VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
+   }
 
    VkImageBlit region = {};
    region.srcSubresource.aspectMask = src->aspect;
@@ -152,6 +188,12 @@ zink_blit(struct pipe_context *pctx,
          return;
    }
 
+   struct zink_resource *src = zink_resource(info->src.resource);
+   struct zink_resource *dst = zink_resource(info->dst.resource);
+   /* if we're copying between resources with matching aspects then we can probably just copy_region */
+   if (src->aspect == dst->aspect && util_try_blit_via_copy_region(pctx, info))
+      return;
+
    if (!util_blitter_is_blit_supported(ctx->blitter, info)) {
       debug_printf("blit unsupported %s -> %s\n",
               util_format_short_name(info->src.resource->format),
@@ -171,13 +213,14 @@ zink_blit(struct pipe_context *pctx,
    util_blitter_save_scissor(ctx->blitter, ctx->scissor_states);
    util_blitter_save_fragment_sampler_states(ctx->blitter,
                                              ctx->num_samplers[PIPE_SHADER_FRAGMENT],
-                                             (void **)ctx->samplers[PIPE_SHADER_FRAGMENT]);
+                                             ctx->sampler_states[PIPE_SHADER_FRAGMENT]);
    util_blitter_save_fragment_sampler_views(ctx->blitter,
                                             ctx->num_image_views[PIPE_SHADER_FRAGMENT],
                                             ctx->image_views[PIPE_SHADER_FRAGMENT]);
    util_blitter_save_fragment_constant_buffer_slot(ctx->blitter, ctx->ubos[PIPE_SHADER_FRAGMENT]);
    util_blitter_save_vertex_buffer_slot(ctx->blitter, ctx->buffers);
    util_blitter_save_sample_mask(ctx->blitter, ctx->gfx_pipeline_state.sample_mask);
+   util_blitter_save_so_targets(ctx->blitter, ctx->num_so_targets, ctx->so_targets);
 
    util_blitter_blit(ctx->blitter, info);
 }